4010 lines
171 KiB
Java
4010 lines
171 KiB
Java
/*
|
|
* Copyright 2022 Google LLC
|
|
*
|
|
* 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.google.android.libraries.mobiledatadownload;
|
|
|
|
import static com.google.common.labs.truth.FutureSubject.assertThat;
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
import static org.junit.Assert.assertNull;
|
|
import static org.junit.Assert.assertThrows;
|
|
import static org.junit.Assert.fail;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
|
import static org.mockito.ArgumentMatchers.anyList;
|
|
import static org.mockito.ArgumentMatchers.anyLong;
|
|
import static org.mockito.Mockito.doThrow;
|
|
import static org.mockito.Mockito.eq;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.verifyNoInteractions;
|
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import android.accounts.Account;
|
|
import android.content.Context;
|
|
import android.net.Uri;
|
|
import androidx.test.core.app.ApplicationProvider;
|
|
import com.google.android.libraries.mobiledatadownload.DownloadException.DownloadResultCode;
|
|
import com.google.android.libraries.mobiledatadownload.TaskScheduler.ConstraintOverrides;
|
|
import com.google.android.libraries.mobiledatadownload.TaskScheduler.NetworkState;
|
|
import com.google.android.libraries.mobiledatadownload.account.AccountUtil;
|
|
import com.google.android.libraries.mobiledatadownload.file.SynchronousFileStorage;
|
|
import com.google.android.libraries.mobiledatadownload.file.backends.AndroidFileBackend;
|
|
import com.google.android.libraries.mobiledatadownload.file.openers.WriteStreamOpener;
|
|
import com.google.android.libraries.mobiledatadownload.internal.MobileDataDownloadManager;
|
|
import com.google.android.libraries.mobiledatadownload.internal.collect.GroupKeyAndGroup;
|
|
import com.google.android.libraries.mobiledatadownload.internal.logging.EventLogger;
|
|
import com.google.android.libraries.mobiledatadownload.internal.logging.testing.FakeEventLogger;
|
|
import com.google.android.libraries.mobiledatadownload.internal.util.ProtoConversionUtil;
|
|
import com.google.android.libraries.mobiledatadownload.lite.Downloader;
|
|
import com.google.android.libraries.mobiledatadownload.monitor.DownloadProgressMonitor;
|
|
import com.google.android.libraries.mobiledatadownload.testing.FakeTimeSource;
|
|
import com.google.android.libraries.mobiledatadownload.testing.TestFlags;
|
|
import com.google.common.base.Optional;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableMap;
|
|
import com.google.common.labs.concurrent.LabsFutures;
|
|
import com.google.common.util.concurrent.FutureCallback;
|
|
import com.google.common.util.concurrent.Futures;
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
|
import com.google.common.util.concurrent.MoreExecutors;
|
|
import com.google.mobiledatadownload.ClientConfigProto.ClientFile;
|
|
import com.google.mobiledatadownload.ClientConfigProto.ClientFileGroup;
|
|
import com.google.mobiledatadownload.ClientConfigProto.ClientFileGroup.Status;
|
|
import com.google.mobiledatadownload.DownloadConfigProto.DataFile;
|
|
import com.google.mobiledatadownload.DownloadConfigProto.DataFileGroup;
|
|
import com.google.mobiledatadownload.DownloadConfigProto.DownloadConditions;
|
|
import com.google.mobiledatadownload.DownloadConfigProto.DownloadConditions.DeviceNetworkPolicy;
|
|
import com.google.mobiledatadownload.LogProto.DataDownloadFileGroupStats;
|
|
import com.google.mobiledatadownload.internal.MetadataProto;
|
|
import com.google.mobiledatadownload.internal.MetadataProto.DataFileGroupInternal;
|
|
import com.google.mobiledatadownload.internal.MetadataProto.GroupKey;
|
|
import com.google.protobuf.Any;
|
|
import com.google.protobuf.ByteString;
|
|
import com.google.protobuf.StringValue;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.concurrent.CancellationException;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import org.junit.After;
|
|
import org.junit.Before;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.Captor;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.MockitoJUnit;
|
|
import org.mockito.junit.MockitoRule;
|
|
import org.robolectric.RobolectricTestRunner;
|
|
|
|
/** Tests for {@link com.google.android.libraries.mobiledatadownload.MobileDataDownload}. */
|
|
@RunWith(RobolectricTestRunner.class)
|
|
public class MobileDataDownloadTest {
|
|
private static final Context context = ApplicationProvider.getApplicationContext();
|
|
|
|
private static final String FILE_GROUP_NAME_1 = "test-group-1";
|
|
private static final String FILE_GROUP_NAME_2 = "test-group-2";
|
|
private static final String FILE_ID_1 = "test-file-1";
|
|
private static final String FILE_ID_2 = "test-file-2";
|
|
private static final String FILE_CHECKSUM_1 = "c1ef7864c76a99ae738ddad33882ed65972c99cc";
|
|
private static final String FILE_URL_1 = "https://www.gstatic.com/suggest-dev/odws1_test_4.jar";
|
|
private static final int FILE_SIZE_1 = 85769;
|
|
|
|
private static final String FILE_CHECKSUM_2 = "a1cba9d87b1440f41ce9e7da38c43e1f6bd7d5df";
|
|
private static final String FILE_URL_2 = "https://www.gstatic.com/suggest-dev/odws1_empty.jar";
|
|
private static final int FILE_SIZE_2 = 554;
|
|
|
|
private static final DataFileGroup FILE_GROUP_1 =
|
|
createDataFileGroup(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
/* versionNumber= */ 1,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_1},
|
|
new String[] {FILE_CHECKSUM_1},
|
|
new String[] {FILE_URL_1},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
|
|
private static final DataFileGroupInternal FILE_GROUP_INTERNAL_1 =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
/* versionNumber= */ 5,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_1},
|
|
new String[] {FILE_CHECKSUM_1},
|
|
new String[] {FILE_URL_1},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
|
|
private final Uri onDeviceUri1 =
|
|
Uri.parse(
|
|
"android://com.google.android.libraries.mobiledatadownload/files/datadownload/shared/public/file_1");
|
|
private final Uri onDeviceDirUri =
|
|
Uri.parse(
|
|
"android://com.google.android.libraries.mobiledatadownload/files/datadownload/shared/public/dir");
|
|
private final Uri onDeviceDirFileUri1 =
|
|
Uri.parse(
|
|
"android://com.google.android.libraries.mobiledatadownload/files/datadownload/shared/public/dir/file_1");
|
|
private final String onDeviceDirFile1Content = "Test file 1.";
|
|
private final Uri onDeviceDirFileUri2 =
|
|
Uri.parse(
|
|
"android://com.google.android.libraries.mobiledatadownload/files/datadownload/shared/public/dir/file_2");
|
|
private final String onDeviceDirFile2Content = "Test file 2.";
|
|
private final Uri onDeviceDirFileUri3 =
|
|
Uri.parse(
|
|
"android://com.google.android.libraries.mobiledatadownload/files/datadownload/shared/public/dir/sub/file");
|
|
private final String onDeviceDirFile3Content = "Test file 3 in sub-dir.";
|
|
|
|
private final TestFlags flags = new TestFlags();
|
|
private SynchronousFileStorage fileStorage;
|
|
private FakeTimeSource timeSource;
|
|
private FakeEventLogger fakeEventLogger;
|
|
|
|
@Mock EventLogger mockEventLogger;
|
|
@Mock MobileDataDownloadManager mockMobileDataDownloadManager;
|
|
@Mock TaskScheduler mockTaskScheduler;
|
|
@Mock FileGroupPopulator mockFileGroupPopulator;
|
|
@Mock DownloadProgressMonitor mockDownloadMonitor;
|
|
@Mock Downloader singleFileDownloader;
|
|
|
|
@Captor ArgumentCaptor<GroupKey> groupKeyCaptor;
|
|
@Captor ArgumentCaptor<List<GroupKey>> groupKeysCaptor;
|
|
|
|
// Note: Executor must not be a single thread executor.
|
|
ListeningExecutorService controlExecutor =
|
|
MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
|
|
|
|
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
|
|
|
|
@Before
|
|
public void setUp() throws IOException {
|
|
fileStorage =
|
|
new SynchronousFileStorage(
|
|
ImmutableList.of(AndroidFileBackend.builder(context).build()) /*backends*/);
|
|
createFile(onDeviceUri1, "test");
|
|
if (!fileStorage.exists(onDeviceDirUri)) {
|
|
fileStorage.createDirectory(onDeviceDirUri);
|
|
}
|
|
createFile(onDeviceDirFileUri1, onDeviceDirFile1Content);
|
|
createFile(onDeviceDirFileUri2, onDeviceDirFile2Content);
|
|
createFile(onDeviceDirFileUri3, onDeviceDirFile3Content);
|
|
timeSource = new FakeTimeSource();
|
|
fakeEventLogger = new FakeEventLogger();
|
|
}
|
|
|
|
@After
|
|
public void tearDown() throws Exception {
|
|
if (fileStorage.exists(onDeviceUri1)) {
|
|
fileStorage.deleteFile(onDeviceUri1);
|
|
}
|
|
if (fileStorage.exists(onDeviceDirFileUri1)) {
|
|
fileStorage.deleteFile(onDeviceDirFileUri1);
|
|
}
|
|
if (fileStorage.exists(onDeviceDirFileUri2)) {
|
|
fileStorage.deleteFile(onDeviceDirFileUri2);
|
|
}
|
|
if (fileStorage.exists(onDeviceDirFileUri3)) {
|
|
fileStorage.deleteFile(onDeviceDirFileUri3);
|
|
}
|
|
}
|
|
|
|
private void createFile(Uri uri, String content) throws IOException {
|
|
try (OutputStream out = fileStorage.open(uri, WriteStreamOpener.create())) {
|
|
out.write(content.getBytes(UTF_8));
|
|
}
|
|
}
|
|
|
|
private void expectErrorLogMessage(String message) {}
|
|
|
|
@Test
|
|
public void buildGetFileGroupsByFilterRequest() throws Exception {
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
GetFileGroupsByFilterRequest request1 =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.setAccountOptional(Optional.of(account))
|
|
.build();
|
|
assertThat(request1.groupNameOptional()).hasValue(FILE_GROUP_NAME_1);
|
|
assertThat(request1.accountOptional()).hasValue(account);
|
|
|
|
GetFileGroupsByFilterRequest request2 =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.build();
|
|
assertThat(request2.groupNameOptional()).hasValue(FILE_GROUP_NAME_1);
|
|
assertThat(request2.accountOptional()).isAbsent();
|
|
|
|
GetFileGroupsByFilterRequest.Builder builder = GetFileGroupsByFilterRequest.newBuilder();
|
|
|
|
assertThrows(IllegalArgumentException.class, builder::build);
|
|
}
|
|
|
|
@Test
|
|
public void buildGetFileGroupsByFilterRequest_groupWithNoAccountOnly() {
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
GetFileGroupsByFilterRequest.Builder builder =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupWithNoAccountOnly(true)
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.setAccountOptional(Optional.of(account));
|
|
|
|
// Make sure that when request account independent groups, accountOptional should be absent.
|
|
assertThrows(IllegalArgumentException.class, builder::build);
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroup() throws Exception {
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
any(GroupKey.class), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(true));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
assertThat(
|
|
mobileDataDownload
|
|
.addFileGroup(
|
|
AddFileGroupRequest.newBuilder().setDataFileGroup(FILE_GROUP_1).build())
|
|
.get())
|
|
.isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroup_onFailure() throws Exception {
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
any(GroupKey.class), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(false));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
assertThat(
|
|
mobileDataDownload
|
|
.addFileGroup(
|
|
AddFileGroupRequest.newBuilder().setDataFileGroup(FILE_GROUP_1).build())
|
|
.get())
|
|
.isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroup_invalidOwnerPackageName() throws Exception {
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
any(GroupKey.class), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(true));
|
|
|
|
// Owner Package should be same as the app package.
|
|
DataFileGroup dataFileGroup =
|
|
createDataFileGroup(
|
|
FILE_GROUP_NAME_1,
|
|
"PACKAGE_NAME",
|
|
1 /* versionNumber */,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_1},
|
|
new String[] {FILE_CHECKSUM_1},
|
|
new String[] {FILE_URL_1},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
null /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
expectErrorLogMessage(
|
|
"MobileDataDownload: Added group = 'test-group-1' with wrong owner package:"
|
|
+ " 'com.google.android.libraries.mobiledatadownload' v.s. 'PACKAGE_NAME' ");
|
|
assertThat(
|
|
mobileDataDownload
|
|
.addFileGroup(
|
|
AddFileGroupRequest.newBuilder().setDataFileGroup(dataFileGroup).build())
|
|
.get())
|
|
.isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroupWithFileGroupKey() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
groupKeyCaptor.capture(), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(true));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
AddFileGroupRequest addFileGroupRequest =
|
|
AddFileGroupRequest.newBuilder()
|
|
.setDataFileGroup(FILE_GROUP_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.build();
|
|
|
|
assertThat(mobileDataDownload.addFileGroup(addFileGroupRequest).get()).isTrue();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
verify(mockMobileDataDownloadManager)
|
|
.addGroupForDownloadInternal(
|
|
eq(groupKey), eq(ProtoConversionUtil.convert(FILE_GROUP_1)), any());
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroupWithFileGroupKey_onFailure() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
groupKeyCaptor.capture(), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(false));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
AddFileGroupRequest addFileGroupRequest =
|
|
AddFileGroupRequest.newBuilder()
|
|
.setDataFileGroup(FILE_GROUP_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.build();
|
|
|
|
assertThat(mobileDataDownload.addFileGroup(addFileGroupRequest).get()).isFalse();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
verify(mockMobileDataDownloadManager)
|
|
.addGroupForDownloadInternal(
|
|
eq(groupKey), eq(ProtoConversionUtil.convert(FILE_GROUP_1)), any());
|
|
}
|
|
|
|
@Test
|
|
public void addFileGroupWithFileGroupKey_nullAccount() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.addGroupForDownloadInternal(
|
|
groupKeyCaptor.capture(), any(DataFileGroupInternal.class), any()))
|
|
.thenReturn(Futures.immediateFuture(true));
|
|
|
|
DataFileGroup dataFileGroup =
|
|
createDataFileGroup(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
1 /* versionNumber */,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_1},
|
|
new String[] {FILE_CHECKSUM_1},
|
|
new String[] {FILE_URL_1},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AddFileGroupRequest addFileGroupRequest =
|
|
AddFileGroupRequest.newBuilder().setDataFileGroup(dataFileGroup).build();
|
|
|
|
assertThat(mobileDataDownload.addFileGroup(addFileGroupRequest).get()).isTrue();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
verify(mockMobileDataDownloadManager)
|
|
.addGroupForDownloadInternal(
|
|
eq(groupKey), eq(ProtoConversionUtil.convert(dataFileGroup)), any());
|
|
}
|
|
|
|
@Test
|
|
public void removeFileGroup_onSuccess_returnsTrue() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.removeFileGroup(groupKeyCaptor.capture(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(null /* Void */));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
RemoveFileGroupRequest removeFileGroupRequest =
|
|
RemoveFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build();
|
|
|
|
assertThat(mobileDataDownload.removeFileGroup(removeFileGroupRequest).get()).isTrue();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void removeFileGroup_onFailure_returnsFalse() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
doThrow(new IOException())
|
|
.when(mockMobileDataDownloadManager)
|
|
.removeFileGroup(groupKeyCaptor.capture(), /* pendingOnly= */ eq(false));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
RemoveFileGroupRequest removeFileGroupRequest =
|
|
RemoveFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build();
|
|
|
|
ExecutionException exception =
|
|
assertThrows(
|
|
ExecutionException.class,
|
|
() -> mobileDataDownload.removeFileGroup(removeFileGroupRequest).get());
|
|
assertThat(exception).hasCauseThat().isInstanceOf(IOException.class);
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void removeFileGroup_withAccount_returnsTrue() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.removeFileGroup(
|
|
groupKeyCaptor.capture(), /* pendingOnly= */ eq(false)))
|
|
.thenReturn(Futures.immediateFuture(null /* Void */));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
RemoveFileGroupRequest removeFileGroupRequest =
|
|
RemoveFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.build();
|
|
|
|
assertThat(mobileDataDownload.removeFileGroup(removeFileGroupRequest).get()).isTrue();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void removeFileGroup_withVariantId_returnsTrue() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.removeFileGroup(
|
|
groupKeyCaptor.capture(), /* pendingOnly= */ eq(false)))
|
|
.thenReturn(Futures.immediateFuture(null /* Void */));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
RemoveFileGroupRequest removeFileGroupRequest =
|
|
RemoveFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVariantIdOptional(Optional.of("en"))
|
|
.build();
|
|
|
|
assertThat(mobileDataDownload.removeFileGroup(removeFileGroupRequest).get()).isTrue();
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setVariantId("en")
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setBuildId(10).setVariantId("test-variant").build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_withDirectory() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceDirUri)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(3);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
List<ClientFile> clientFileList = clientFileGroup.getFileList();
|
|
assertThat(clientFileList)
|
|
.contains(
|
|
ClientFile.newBuilder()
|
|
.setFileId("/file_1")
|
|
.setFileUri(onDeviceDirFileUri1.toString())
|
|
.setFullSizeInBytes(onDeviceDirFile1Content.getBytes(UTF_8).length)
|
|
.build());
|
|
assertThat(clientFileList)
|
|
.contains(
|
|
ClientFile.newBuilder()
|
|
.setFileId("/file_2")
|
|
.setFileUri(onDeviceDirFileUri2.toString())
|
|
.setFullSizeInBytes(onDeviceDirFile2Content.getBytes(UTF_8).length)
|
|
.build());
|
|
assertThat(clientFileList)
|
|
.contains(
|
|
ClientFile.newBuilder()
|
|
.setFileId("/sub/file")
|
|
.setFileUri(onDeviceDirFileUri3.toString())
|
|
.setFullSizeInBytes(onDeviceDirFile3Content.getBytes(UTF_8).length)
|
|
.build());
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_withDirectory_withTraverseDisabled() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceDirUri)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder()
|
|
.setPreserveZipDirectories(true)
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.build())
|
|
.get();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
List<ClientFile> clientFileList = clientFileGroup.getFileList();
|
|
assertThat(clientFileList)
|
|
.contains(
|
|
ClientFile.newBuilder()
|
|
.setFileId("test-file-1")
|
|
.setFileUri(onDeviceDirUri.toString())
|
|
.setFullSizeInBytes(FILE_SIZE_1)
|
|
.build());
|
|
assertThat(fileStorage.isDirectory(Uri.parse(clientFileList.get(0).getFileUri()))).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void removeFileGroupsByFilter_withAccountSpecified_removesMatchingAccountGroups()
|
|
throws Exception {
|
|
List<GroupKeyAndGroup> keyToGroupList = new ArrayList<>();
|
|
Account account1 = AccountUtil.create("account-name", "account-type");
|
|
Account account2 = AccountUtil.create("account-name2", "account-type");
|
|
|
|
DataFileGroupInternal downloadedFileGroup = FILE_GROUP_INTERNAL_1.toBuilder().build();
|
|
DataFileGroupInternal pendingFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setFileGroupVersionNumber(6).build();
|
|
|
|
GroupKey account1GroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account1))
|
|
.build();
|
|
GroupKey downloadedAccount1GroupKey = account1GroupKey.toBuilder().setDownloaded(true).build();
|
|
GroupKey pendingAccount1GroupKey = account1GroupKey.toBuilder().setDownloaded(false).build();
|
|
|
|
GroupKey account2GroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account2))
|
|
.build();
|
|
GroupKey downloadedAccount2GroupKey = account2GroupKey.toBuilder().setDownloaded(true).build();
|
|
GroupKey pendingAccount2GroupKey = account2GroupKey.toBuilder().setDownloaded(false).build();
|
|
|
|
GroupKey noAccountGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
GroupKey downloadedGroupKey = noAccountGroupKey.toBuilder().setDownloaded(true).build();
|
|
GroupKey pendingGroupKey = noAccountGroupKey.toBuilder().setDownloaded(false).build();
|
|
|
|
keyToGroupList.add(GroupKeyAndGroup.create(downloadedGroupKey, downloadedFileGroup));
|
|
keyToGroupList.add(GroupKeyAndGroup.create(downloadedAccount1GroupKey, downloadedFileGroup));
|
|
keyToGroupList.add(GroupKeyAndGroup.create(downloadedAccount2GroupKey, downloadedFileGroup));
|
|
keyToGroupList.add(GroupKeyAndGroup.create(pendingGroupKey, pendingFileGroup));
|
|
keyToGroupList.add(GroupKeyAndGroup.create(pendingAccount1GroupKey, pendingFileGroup));
|
|
keyToGroupList.add(GroupKeyAndGroup.create(pendingAccount2GroupKey, pendingFileGroup));
|
|
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(keyToGroupList));
|
|
when(mockMobileDataDownloadManager.removeFileGroups(groupKeysCaptor.capture()))
|
|
.thenReturn(Futures.immediateVoidFuture());
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
/* foregroundDownloadServiceClassOptional= */ Optional.absent(),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// Setup request that matches all fresh groups, but also include account to make sure only
|
|
// account associated file groups are removed
|
|
RemoveFileGroupsByFilterRequest removeFileGroupsByFilterRequest =
|
|
RemoveFileGroupsByFilterRequest.newBuilder()
|
|
.setAccountOptional(Optional.of(account1))
|
|
.build();
|
|
|
|
RemoveFileGroupsByFilterResponse response =
|
|
mobileDataDownload.removeFileGroupsByFilter(removeFileGroupsByFilterRequest).get();
|
|
|
|
assertThat(response.removedFileGroupsCount()).isEqualTo(1);
|
|
verify(mockMobileDataDownloadManager, times(1)).removeFileGroups(anyList());
|
|
List<GroupKey> removedGroupKeys = groupKeysCaptor.getValue();
|
|
assertThat(removedGroupKeys).containsExactly(account1GroupKey);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_nullFileUri() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFailedFuture(
|
|
DownloadException.builder()
|
|
.setDownloadResultCode(DownloadResultCode.UNKNOWN_ERROR)
|
|
.setMessage("Fail to download file group")
|
|
.build()));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
assertNull(
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get());
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_null() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
assertNull(
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get());
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_withAccount() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.build())
|
|
.get();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_withVariantId() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setVariantId("en").build();
|
|
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVariantIdOptional(Optional.of("en"))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getAccount()).isEmpty();
|
|
assertThat(clientFileGroup.getVariantId()).isEqualTo("en");
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setVariantId("en")
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(groupKey);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_includesIdentifyingProperties() throws Exception {
|
|
Any customProperty =
|
|
Any.newBuilder()
|
|
.setTypeUrl("type.googleapis.com/google.protobuf.stringvalue")
|
|
.setValue(StringValue.of("TEST_PROPERTY").toByteString())
|
|
.build();
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder()
|
|
.setBuildId(1L)
|
|
.setVariantId("testvariant")
|
|
.setCustomProperty(customProperty)
|
|
.build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getBuildId()).isEqualTo(1L);
|
|
assertThat(clientFileGroup.getVariantId()).isEqualTo("testvariant");
|
|
assertThat(clientFileGroup.getCustomProperty()).isEqualTo(customProperty);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_includesLocale() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().addLocale("en-US").addLocale("en-CA").build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getLocaleList()).containsExactly("en-US", "en-CA");
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_includesGroupLevelMetadataWhenProvided() throws Exception {
|
|
Any customMetadata =
|
|
Any.newBuilder()
|
|
.setTypeUrl("type.googleapis.com/google.protobuf.stringvalue")
|
|
.setValue(StringValue.of("TEST_METADATA").toByteString())
|
|
.build();
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setCustomMetadata(customMetadata).build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getCustomMetadata()).isEqualTo(customMetadata);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_includesFileLevelMetadataWhenProvided() throws Exception {
|
|
Any customMetadata =
|
|
Any.newBuilder()
|
|
.setTypeUrl("type.googleapis.com/google.protobuf.stringvalue")
|
|
.setValue(StringValue.of("TEST_METADATA").toByteString())
|
|
.build();
|
|
DataFileGroupInternal dataFileGroup =
|
|
DataFileGroupInternal.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.addFile(
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setUrlToDownload(FILE_URL_1)
|
|
.setCustomMetadata(customMetadata)
|
|
.build())
|
|
.addFile(
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_2)
|
|
.setUrlToDownload(FILE_URL_2)
|
|
.build())
|
|
.build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(
|
|
dataFileGroup.getFile(0),
|
|
onDeviceUri1,
|
|
dataFileGroup.getFile(1),
|
|
onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.hasCustomMetadata()).isFalse();
|
|
|
|
ClientFile clientFile1 =
|
|
clientFileGroup.getFile(0).getFileId().equals(FILE_ID_1)
|
|
? clientFileGroup.getFile(0)
|
|
: clientFileGroup.getFile(1);
|
|
ClientFile clientFile2 =
|
|
clientFileGroup.getFile(0).getFileId().equals(FILE_ID_1)
|
|
? clientFileGroup.getFile(1)
|
|
: clientFileGroup.getFile(0);
|
|
|
|
assertThat(clientFile1.hasCustomMetadata()).isTrue();
|
|
assertThat(clientFile1.getCustomMetadata()).isEqualTo(customMetadata);
|
|
assertThat(clientFile2.hasCustomMetadata()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_whenVerifyIsolatedStructureIsFalse_skipsStructureVerification()
|
|
throws Exception {
|
|
MetadataProto.DataFile isolatedStructureFile =
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setChecksumType(MetadataProto.DataFile.ChecksumType.NONE)
|
|
.setUrlToDownload(FILE_URL_1)
|
|
.setRelativeFilePath("mycustom/file.txt")
|
|
.build();
|
|
DataFileGroupInternal isolatedStructureGroup =
|
|
DataFileGroupInternal.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setPreserveFilenamesAndIsolateFiles(true)
|
|
.addFile(isolatedStructureFile)
|
|
.build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(isolatedStructureGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
isolatedStructureGroup, /* verifyIsolatedStructure= */ false))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(isolatedStructureGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVerifyIsolatedStructure(false)
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getFile(0).getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
// Verify getting the file uri bypassed the verify check.
|
|
verify(mockMobileDataDownloadManager, never()).getDataFileUris(any(), eq(true));
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_whenVerifyIsolatedStructureIsTrue_returnsNullOnInvalidStructure()
|
|
throws Exception {
|
|
MetadataProto.DataFile isolatedStructureFile =
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setChecksumType(MetadataProto.DataFile.ChecksumType.NONE)
|
|
.setUrlToDownload(FILE_URL_1)
|
|
.setRelativeFilePath("mycustom/file.txt")
|
|
.build();
|
|
DataFileGroupInternal isolatedStructureGroup =
|
|
DataFileGroupInternal.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setPreserveFilenamesAndIsolateFiles(true)
|
|
.addFile(isolatedStructureFile)
|
|
.build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(isolatedStructureGroup));
|
|
|
|
// Mock that verification failed
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
isolatedStructureGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// Assert that a failure to verify the isolated structure returns a null group
|
|
assertThat(
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVerifyIsolatedStructure(true)
|
|
.build())
|
|
.get())
|
|
.isNull();
|
|
|
|
// Verify getting the file uri did not bypass the verify check.
|
|
verify(mockMobileDataDownloadManager, never()).getDataFileUris(any(), eq(false));
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_fileGroupFound_logsQueryStatsForFileGroup() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setBuildId(10).setVariantId("test-variant").build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(
|
|
any(GroupKey.class), /* downloaded= */ eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
fakeEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
/* customValidatorOptional= */ Optional.absent(),
|
|
timeSource);
|
|
|
|
ClientFileGroup unused =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
List<DataDownloadFileGroupStats> fileGroupDetailsList =
|
|
fakeEventLogger.getLoggedMddQueryStats();
|
|
|
|
assertThat(fileGroupDetailsList).hasSize(1);
|
|
DataDownloadFileGroupStats fileGroupStats = fileGroupDetailsList.get(0);
|
|
assertThat(fileGroupStats.getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.getFileGroupVersionNumber()).isEqualTo(5);
|
|
assertThat(fileGroupStats.getBuildId()).isEqualTo(10);
|
|
assertThat(fileGroupStats.getVariantId()).isEqualTo("test-variant");
|
|
assertThat(fileGroupStats.getFileCount()).isEqualTo(1);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_fileGroupFound_doesNotOverLog() throws Exception {
|
|
DataFileGroupInternal dataFileGroup = FILE_GROUP_INTERNAL_1;
|
|
when(mockMobileDataDownloadManager.getFileGroup(
|
|
any(GroupKey.class), /* downloaded= */ eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
/* customValidatorOptional= */ Optional.absent(),
|
|
timeSource);
|
|
|
|
ClientFileGroup unused =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
verify(mockEventLogger).logMddQueryStats(any());
|
|
verify(mockEventLogger).logMddLibApiResultLog(any());
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_fileGroupNotFound_doesNotOverLog() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(
|
|
any(GroupKey.class), /* downloaded= */ eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
/* customValidatorOptional= */ Optional.absent(),
|
|
timeSource);
|
|
|
|
ClientFileGroup unused =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
verify(mockEventLogger).logMddLibApiResultLog(any());
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsException_doesNotOverLog() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFailedFuture(new Exception()));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
/* customValidatorOptional= */ Optional.absent(),
|
|
timeSource);
|
|
|
|
assertThrows(
|
|
ExecutionException.class,
|
|
() ->
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get());
|
|
|
|
verify(mockEventLogger).logMddLibApiResultLog(any());
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
/**
|
|
* Helper function to test that expected errors are being logged.
|
|
*
|
|
* <p>causeThrowable is used to check for cause only if expectedThrowable is instance of
|
|
* ExecutionException.
|
|
*/
|
|
private <T extends Throwable> void getFileGroupErrorLoggingTestHelper(
|
|
ListenableFuture<?> getFileGroupResultFuture,
|
|
Class<T> expectedThrowable,
|
|
Class<?> causeThrowable,
|
|
int code)
|
|
throws Exception {
|
|
long latencyNs = 1000;
|
|
when(mockMobileDataDownloadManager.getFileGroup(
|
|
any(GroupKey.class), /* downloaded= */ eq(true)))
|
|
.thenAnswer(
|
|
invocation -> {
|
|
// Advancing time source to test latency.
|
|
timeSource.advance(latencyNs, TimeUnit.NANOSECONDS);
|
|
return getFileGroupResultFuture;
|
|
});
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
fakeEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
/* customValidatorOptional= */ Optional.absent(),
|
|
timeSource);
|
|
|
|
Throwable thrown =
|
|
assertThrows(
|
|
expectedThrowable,
|
|
() ->
|
|
mobileDataDownload
|
|
.getFileGroup(
|
|
GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get());
|
|
|
|
if (thrown instanceof ExecutionException) {
|
|
assertThat(thrown).hasCauseThat().isInstanceOf(causeThrowable);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsCancelledException_logsCancelled() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateCancelledFuture(), CancellationException.class, null, 0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsUnknownException_logsFailureWithoutCause() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new Exception()),
|
|
ExecutionException.class,
|
|
Exception.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsInterruptedException_logsInterrupted() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new InterruptedException()),
|
|
ExecutionException.class,
|
|
InterruptedException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsIOException_logsIOError() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new IOException()),
|
|
ExecutionException.class,
|
|
IOException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsIllegalStateException_logsIllegalState() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new IllegalStateException()),
|
|
ExecutionException.class,
|
|
IllegalStateException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsIllegalArgumentException_logsIllegalArgument() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new IllegalArgumentException()),
|
|
ExecutionException.class,
|
|
IllegalArgumentException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsUnsupportedOperationException_logsUnsupportedOperation()
|
|
throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(new UnsupportedOperationException()),
|
|
ExecutionException.class,
|
|
UnsupportedOperationException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroup_throwsDownloadException_logsDownloadError() throws Exception {
|
|
getFileGroupErrorLoggingTestHelper(
|
|
Futures.immediateFailedFuture(
|
|
DownloadException.builder()
|
|
.setDownloadResultCode(DownloadResultCode.UNSPECIFIED)
|
|
.build()),
|
|
ExecutionException.class,
|
|
DownloadException.class,
|
|
0);
|
|
}
|
|
|
|
@Test
|
|
public void readDataFileGroup_returnsFileGroup() throws Exception {
|
|
DataFileGroupInternal dataFileGroupInternal =
|
|
DataFileGroupInternal.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.addFile(
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setUrlToDownload(FILE_URL_1)
|
|
.build())
|
|
.addFile(
|
|
MetadataProto.DataFile.newBuilder()
|
|
.setFileId(FILE_ID_2)
|
|
.setUrlToDownload(FILE_URL_2)
|
|
.build())
|
|
.build();
|
|
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroupInternal));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroupInternal, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(
|
|
dataFileGroupInternal.getFile(0),
|
|
onDeviceUri1,
|
|
dataFileGroupInternal.getFile(1),
|
|
onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
DataFileGroup dataFileGroup =
|
|
mobileDataDownload
|
|
.readDataFileGroup(
|
|
ReadDataFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
assertThat(dataFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(dataFileGroup.getFileList())
|
|
.containsExactly(
|
|
DataFile.newBuilder().setFileId(FILE_ID_1).setUrlToDownload(FILE_URL_1).build(),
|
|
DataFile.newBuilder().setFileId(FILE_ID_2).setUrlToDownload(FILE_URL_2).build());
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroupsByFilter_singleGroup() throws Exception {
|
|
List<GroupKeyAndGroup> keyDataFileGroupList = new ArrayList<>();
|
|
|
|
DataFileGroupInternal downloadedFileGroup = FILE_GROUP_INTERNAL_1;
|
|
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(eq(groupKey), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(downloadedFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
downloadedFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(downloadedFileGroup.getFile(0), onDeviceUri1)));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(true).build(), downloadedFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
7 /* versionNumber */,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
pendingFileGroup =
|
|
pendingFileGroup.toBuilder()
|
|
.setFile(0, pendingFileGroup.getFile(0).toBuilder().setDownloadedFileByteSize(222222))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(false).build(), pendingFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup2 =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_2,
|
|
context.getPackageName(),
|
|
4 /* versionNumber */,
|
|
new String[] {FILE_ID_1, FILE_ID_2},
|
|
new int[] {FILE_SIZE_1, FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_1, FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_1, FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
GroupKey groupKey2 =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_2)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey2, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup2));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup2, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey2.toBuilder().setDownloaded(false).build(), pendingFileGroup2));
|
|
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(keyDataFileGroupList));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// We should get back 2 groups for FILE_GROUP_NAME_1.
|
|
GetFileGroupsByFilterRequest getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.build();
|
|
ImmutableList<ClientFileGroup> clientFileGroups =
|
|
mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).hasSize(2);
|
|
|
|
ClientFileGroup downloadedClientFileGroup = clientFileGroups.get(0);
|
|
assertThat(downloadedClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(downloadedClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(downloadedClientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(downloadedClientFileGroup.getStatus()).isEqualTo(Status.DOWNLOADED);
|
|
assertThat(downloadedClientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(downloadedClientFileGroup.hasAccount()).isFalse();
|
|
|
|
ClientFile clientFile = downloadedClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
assertThat(clientFile.getFullSizeInBytes()).isEqualTo(FILE_SIZE_1);
|
|
|
|
ClientFileGroup pendingClientFileGroup = clientFileGroups.get(1);
|
|
assertThat(pendingClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(pendingClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup.getVersionNumber()).isEqualTo(7);
|
|
assertThat(pendingClientFileGroup.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(pendingClientFileGroup.hasAccount()).isFalse();
|
|
|
|
clientFile = pendingClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getDownloadSizeInBytes()).isEqualTo(222222);
|
|
assertThat(clientFile.getFileUri()).isEmpty();
|
|
|
|
// We should get back 1 group for FILE_GROUP_NAME_2.
|
|
getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_2))
|
|
.build();
|
|
clientFileGroups = mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
ClientFileGroup pendingClientFileGroup2 = clientFileGroups.get(0);
|
|
assertThat(pendingClientFileGroup2.getGroupName()).isEqualTo(FILE_GROUP_NAME_2);
|
|
assertThat(pendingClientFileGroup2.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup2.getVersionNumber()).isEqualTo(4);
|
|
assertThat(pendingClientFileGroup2.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup2.getFileCount()).isEqualTo(2);
|
|
assertThat(pendingClientFileGroup2.hasAccount()).isFalse();
|
|
|
|
ArgumentCaptor<DataDownloadFileGroupStats> fileGroupDetailsCaptor =
|
|
ArgumentCaptor.forClass(DataDownloadFileGroupStats.class);
|
|
verify(mockEventLogger, times(3)).logMddQueryStats(fileGroupDetailsCaptor.capture());
|
|
|
|
List<DataDownloadFileGroupStats> fileGroupStats = fileGroupDetailsCaptor.getAllValues();
|
|
assertThat(fileGroupStats).hasSize(3);
|
|
assertThat(fileGroupStats.get(0).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(0).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(0).getFileGroupVersionNumber()).isEqualTo(5);
|
|
assertThat(fileGroupStats.get(0).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(1).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(1).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(1).getFileGroupVersionNumber()).isEqualTo(7);
|
|
assertThat(fileGroupStats.get(1).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(2).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_2);
|
|
assertThat(fileGroupStats.get(2).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(2).getFileGroupVersionNumber()).isEqualTo(4);
|
|
assertThat(fileGroupStats.get(2).getFileCount()).isEqualTo(2);
|
|
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroupsByFilter_includeAllGroups() throws Exception {
|
|
List<GroupKeyAndGroup> keyDataFileGroupList = new ArrayList<>();
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
|
|
DataFileGroupInternal downloadedFileGroup = FILE_GROUP_INTERNAL_1;
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
downloadedFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(downloadedFileGroup.getFile(0), onDeviceUri1)));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(true).build(), downloadedFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
7,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(false).build(), pendingFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup2 =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_2,
|
|
context.getPackageName(),
|
|
4 /* versionNumber */,
|
|
new String[] {FILE_ID_1, FILE_ID_2},
|
|
new int[] {FILE_SIZE_1, FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_1, FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_1, FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
GroupKey groupKey2 =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_2)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey2, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup2));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup2, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey2.toBuilder().setDownloaded(false).build(), pendingFileGroup2));
|
|
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(keyDataFileGroupList));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// We should get back all 3 groups for this key.
|
|
GetFileGroupsByFilterRequest getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder().setIncludeAllGroups(true).build();
|
|
List<ClientFileGroup> clientFileGroups =
|
|
mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).hasSize(3);
|
|
|
|
ClientFileGroup downloadedClientFileGroup = clientFileGroups.get(0);
|
|
assertThat(downloadedClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(downloadedClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(downloadedClientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(downloadedClientFileGroup.getStatus()).isEqualTo(Status.DOWNLOADED);
|
|
assertThat(downloadedClientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(downloadedClientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
|
|
ClientFile clientFile = downloadedClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
assertThat(clientFile.getFullSizeInBytes()).isEqualTo(FILE_SIZE_1);
|
|
|
|
ClientFileGroup pendingClientFileGroup = clientFileGroups.get(1);
|
|
assertThat(pendingClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(pendingClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup.getVersionNumber()).isEqualTo(7);
|
|
assertThat(pendingClientFileGroup.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(pendingClientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
|
|
clientFile = pendingClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEmpty();
|
|
|
|
ClientFileGroup pendingClientFileGroup2 = clientFileGroups.get(2);
|
|
assertThat(pendingClientFileGroup2.getGroupName()).isEqualTo(FILE_GROUP_NAME_2);
|
|
assertThat(pendingClientFileGroup2.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup2.getVersionNumber()).isEqualTo(4);
|
|
assertThat(pendingClientFileGroup2.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup2.getFileCount()).isEqualTo(2);
|
|
assertThat(pendingClientFileGroup2.hasAccount()).isFalse();
|
|
|
|
ArgumentCaptor<DataDownloadFileGroupStats> fileGroupDetailsCaptor =
|
|
ArgumentCaptor.forClass(DataDownloadFileGroupStats.class);
|
|
verify(mockEventLogger, times(3)).logMddQueryStats(fileGroupDetailsCaptor.capture());
|
|
|
|
List<DataDownloadFileGroupStats> fileGroupStats = fileGroupDetailsCaptor.getAllValues();
|
|
assertThat(fileGroupStats).hasSize(3);
|
|
assertThat(fileGroupStats.get(0).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(0).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(0).getFileGroupVersionNumber()).isEqualTo(5);
|
|
assertThat(fileGroupStats.get(0).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(1).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(1).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(1).getFileGroupVersionNumber()).isEqualTo(7);
|
|
assertThat(fileGroupStats.get(1).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(2).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_2);
|
|
assertThat(fileGroupStats.get(2).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(2).getFileGroupVersionNumber()).isEqualTo(4);
|
|
assertThat(fileGroupStats.get(2).getFileCount()).isEqualTo(2);
|
|
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroupsByFilter_noData() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(ImmutableList.of()));
|
|
|
|
GetFileGroupsByFilterRequest getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder().setIncludeAllGroups(true).build();
|
|
List<ClientFileGroup> clientFileGroups =
|
|
mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).isEmpty();
|
|
|
|
getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.build();
|
|
clientFileGroups = mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).isEmpty();
|
|
|
|
verifyNoInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroupsByFilter_withAccount() throws Exception {
|
|
List<GroupKeyAndGroup> keyDataFileGroupList = new ArrayList<>();
|
|
|
|
Account account1 = AccountUtil.create("account-name-1", "account-type");
|
|
Account account2 = AccountUtil.create("account-name-2", "account-type");
|
|
|
|
DataFileGroupInternal downloadedFileGroup = FILE_GROUP_INTERNAL_1;
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account1))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey, true))
|
|
.thenReturn(Futures.immediateFuture(downloadedFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
downloadedFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(downloadedFileGroup.getFile(0), onDeviceUri1)));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(true).build(), downloadedFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
7 /* versionNumber */,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(false).build(), pendingFileGroup));
|
|
|
|
DataFileGroupInternal pendingFileGroup2 =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
4 /* versionNumber */,
|
|
new String[] {FILE_ID_1, FILE_ID_2},
|
|
new int[] {FILE_SIZE_1, FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_1, FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_1, FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
GroupKey groupKey2 =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account2))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey2, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup2));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup2, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey2.toBuilder().setDownloaded(false).build(), pendingFileGroup2));
|
|
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(keyDataFileGroupList));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// We should get back 2 groups for FILE_GROUP_NAME_1 with account1.
|
|
GetFileGroupsByFilterRequest getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.setAccountOptional(Optional.of(account1))
|
|
.build();
|
|
ImmutableList<ClientFileGroup> clientFileGroups =
|
|
mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).hasSize(2);
|
|
|
|
ClientFileGroup downloadedClientFileGroup = clientFileGroups.get(0);
|
|
assertThat(downloadedClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(downloadedClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(downloadedClientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(downloadedClientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account1));
|
|
assertThat(downloadedClientFileGroup.getStatus()).isEqualTo(Status.DOWNLOADED);
|
|
assertThat(downloadedClientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
ClientFile clientFile = downloadedClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
assertThat(clientFile.getFullSizeInBytes()).isEqualTo(FILE_SIZE_1);
|
|
|
|
ClientFileGroup pendingClientFileGroup = clientFileGroups.get(1);
|
|
assertThat(pendingClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(pendingClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup.getVersionNumber()).isEqualTo(7);
|
|
assertThat(pendingClientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account1));
|
|
assertThat(pendingClientFileGroup.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
clientFile = pendingClientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEmpty();
|
|
|
|
// We should get back 1 group for FILE_GROUP_NAME_1 with account2.
|
|
getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.setAccountOptional(Optional.of(account2))
|
|
.build();
|
|
clientFileGroups = mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
ClientFileGroup pendingClientFileGroup2 = clientFileGroups.get(0);
|
|
assertThat(pendingClientFileGroup2.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(pendingClientFileGroup2.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup2.getVersionNumber()).isEqualTo(4);
|
|
assertThat(pendingClientFileGroup2.getAccount()).isEqualTo(AccountUtil.serialize(account2));
|
|
assertThat(pendingClientFileGroup2.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup2.getFileCount()).isEqualTo(2);
|
|
|
|
ArgumentCaptor<DataDownloadFileGroupStats> fileGroupDetailsCaptor =
|
|
ArgumentCaptor.forClass(DataDownloadFileGroupStats.class);
|
|
verify(mockEventLogger, times(3)).logMddQueryStats(fileGroupDetailsCaptor.capture());
|
|
|
|
List<DataDownloadFileGroupStats> fileGroupStats = fileGroupDetailsCaptor.getAllValues();
|
|
assertThat(fileGroupStats).hasSize(3);
|
|
assertThat(fileGroupStats.get(0).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(0).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(0).getFileGroupVersionNumber()).isEqualTo(5);
|
|
assertThat(fileGroupStats.get(0).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(1).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(1).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(1).getFileGroupVersionNumber()).isEqualTo(7);
|
|
assertThat(fileGroupStats.get(1).getFileCount()).isEqualTo(1);
|
|
assertThat(fileGroupStats.get(2).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(2).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(2).getFileGroupVersionNumber()).isEqualTo(4);
|
|
assertThat(fileGroupStats.get(2).getFileCount()).isEqualTo(2);
|
|
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void getFileGroupsByFilter_groupWithNoAccountOnly() throws Exception {
|
|
List<GroupKeyAndGroup> keyDataFileGroupList = new ArrayList<>();
|
|
|
|
Account account1 = AccountUtil.create("account-name-1", "account-type");
|
|
Account account2 = AccountUtil.create("account-name-2", "account-type");
|
|
|
|
// downloadedFileGroup is associated with account1.
|
|
DataFileGroupInternal downloadedFileGroup = FILE_GROUP_INTERNAL_1;
|
|
GroupKey groupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account1))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey, true))
|
|
.thenReturn(Futures.immediateFuture(downloadedFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
downloadedFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(downloadedFileGroup.getFile(0), onDeviceUri1)));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey.toBuilder().setDownloaded(true).build(), downloadedFileGroup));
|
|
|
|
// pendingFileGroup is associated with account2.
|
|
DataFileGroupInternal pendingFileGroup =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
/* versionNumber= */ 7,
|
|
new String[] {FILE_ID_1},
|
|
new int[] {FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
GroupKey groupKey2 =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setAccount(AccountUtil.serialize(account2))
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey2, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey2.toBuilder().setDownloaded(false).build(), pendingFileGroup));
|
|
|
|
// pendingFileGroup2 is an account independent group.
|
|
DataFileGroupInternal pendingFileGroup2 =
|
|
createDataFileGroupInternal(
|
|
FILE_GROUP_NAME_1,
|
|
context.getPackageName(),
|
|
/* versionNumber= */ 4,
|
|
new String[] {FILE_ID_1, FILE_ID_2},
|
|
new int[] {FILE_SIZE_1, FILE_SIZE_2},
|
|
new String[] {FILE_CHECKSUM_1, FILE_CHECKSUM_2},
|
|
new String[] {FILE_URL_1, FILE_URL_2},
|
|
DeviceNetworkPolicy.DOWNLOAD_ONLY_ON_WIFI);
|
|
GroupKey groupKey3 =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKey3, false))
|
|
.thenReturn(Futures.immediateFuture(pendingFileGroup2));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
pendingFileGroup2, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(Futures.immediateFuture(ImmutableMap.of()));
|
|
keyDataFileGroupList.add(
|
|
GroupKeyAndGroup.create(
|
|
groupKey3.toBuilder().setDownloaded(false).build(), pendingFileGroup2));
|
|
|
|
when(mockMobileDataDownloadManager.getAllFreshGroups())
|
|
.thenReturn(Futures.immediateFuture(keyDataFileGroupList));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
/* foregroundDownloadServiceClassOptional= */ Optional.absent(),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// We should get back only 1 group for FILE_GROUP_NAME_1 with groupWithNoAccountOnly being set
|
|
// to true.
|
|
GetFileGroupsByFilterRequest getFileGroupsByFilterRequest =
|
|
GetFileGroupsByFilterRequest.newBuilder()
|
|
.setGroupWithNoAccountOnly(true)
|
|
.setGroupNameOptional(Optional.of(FILE_GROUP_NAME_1))
|
|
.build();
|
|
ImmutableList<ClientFileGroup> clientFileGroups =
|
|
mobileDataDownload.getFileGroupsByFilter(getFileGroupsByFilterRequest).get();
|
|
assertThat(clientFileGroups).hasSize(1);
|
|
|
|
ClientFileGroup pendingClientFileGroup = clientFileGroups.get(0);
|
|
assertThat(pendingClientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(pendingClientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(pendingClientFileGroup.getVersionNumber()).isEqualTo(4);
|
|
assertThat(pendingClientFileGroup.getStatus()).isEqualTo(Status.PENDING);
|
|
assertThat(pendingClientFileGroup.getFileCount()).isEqualTo(2);
|
|
assertThat(pendingClientFileGroup.hasAccount()).isFalse();
|
|
|
|
ArgumentCaptor<DataDownloadFileGroupStats> fileGroupDetailsCaptor =
|
|
ArgumentCaptor.forClass(DataDownloadFileGroupStats.class);
|
|
verify(mockEventLogger, times(1)).logMddQueryStats(fileGroupDetailsCaptor.capture());
|
|
|
|
List<DataDownloadFileGroupStats> fileGroupStats = fileGroupDetailsCaptor.getAllValues();
|
|
assertThat(fileGroupStats).hasSize(1);
|
|
assertThat(fileGroupStats.get(0).getFileGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(fileGroupStats.get(0).getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(fileGroupStats.get(0).getFileGroupVersionNumber()).isEqualTo(4);
|
|
assertThat(fileGroupStats.get(0).getFileCount()).isEqualTo(2);
|
|
|
|
verifyNoMoreInteractions(mockEventLogger);
|
|
}
|
|
|
|
@Test
|
|
public void importFiles_whenSuccessful_returns() throws Exception {
|
|
String inlineFileUrl = String.format("inlinefile:sha1:%s", FILE_CHECKSUM_1);
|
|
DataFile inlineFile =
|
|
DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setByteSize(FILE_SIZE_1)
|
|
.setChecksum(FILE_CHECKSUM_1)
|
|
.setUrlToDownload(inlineFileUrl)
|
|
.build();
|
|
ImmutableList<DataFile> updatedDataFileList = ImmutableList.of(inlineFile);
|
|
ImmutableMap<String, FileSource> inlineFileMap =
|
|
ImmutableMap.of(
|
|
FILE_ID_1, FileSource.ofByteString(ByteString.copyFromUtf8("TEST_CONTENT")));
|
|
|
|
// TODO: rely on actual implementation once feature is fully implemented.
|
|
when(mockMobileDataDownloadManager.importFiles(
|
|
any(), anyLong(), any(), any(), any(), any(), any()))
|
|
.thenReturn(Futures.immediateVoidFuture());
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// Since we use mocks, just call the method directly, no need to call addFileGroup first
|
|
mobileDataDownload
|
|
.importFiles(
|
|
ImportFilesRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setBuildId(1)
|
|
.setVariantId("testvariant")
|
|
.setUpdatedDataFileList(updatedDataFileList)
|
|
.setInlineFileMap(inlineFileMap)
|
|
.build())
|
|
.get();
|
|
|
|
// Verify mocks were called
|
|
GroupKey expectedGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
ImmutableList<MetadataProto.DataFile> expectedDataFileList =
|
|
ImmutableList.of(ProtoConversionUtil.convertDataFile(inlineFile));
|
|
verify(mockMobileDataDownloadManager)
|
|
.importFiles(
|
|
eq(expectedGroupKey),
|
|
eq(1L),
|
|
eq("testvariant"),
|
|
eq(expectedDataFileList),
|
|
eq(inlineFileMap),
|
|
eq(Optional.absent()),
|
|
any());
|
|
}
|
|
|
|
@Test
|
|
public void importFiles_whenAccountIsSpecified_usesAccount() throws Exception {
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
String inlineFileUrl = String.format("inlinefile:sha1:%s", FILE_CHECKSUM_1);
|
|
DataFile inlineFile =
|
|
DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setByteSize(FILE_SIZE_1)
|
|
.setChecksum(FILE_CHECKSUM_1)
|
|
.setUrlToDownload(inlineFileUrl)
|
|
.build();
|
|
ImmutableList<DataFile> updatedDataFileList = ImmutableList.of(inlineFile);
|
|
ImmutableMap<String, FileSource> inlineFileMap =
|
|
ImmutableMap.of(
|
|
FILE_ID_1, FileSource.ofByteString(ByteString.copyFromUtf8("TEST_CONTENT")));
|
|
|
|
// TODO: rely on actual implementation once feature is fully implemented.
|
|
when(mockMobileDataDownloadManager.importFiles(
|
|
any(), anyLong(), any(), any(), any(), any(), any()))
|
|
.thenReturn(Futures.immediateVoidFuture());
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// Since we use mocks, just call the method directly, no need to call addFileGroup first
|
|
mobileDataDownload
|
|
.importFiles(
|
|
ImportFilesRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.setBuildId(1)
|
|
.setVariantId("testvariant")
|
|
.setUpdatedDataFileList(updatedDataFileList)
|
|
.setInlineFileMap(inlineFileMap)
|
|
.build())
|
|
.get();
|
|
|
|
// Verify mocks were called
|
|
GroupKey expectedGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccount(AccountUtil.serialize(account))
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
ImmutableList<MetadataProto.DataFile> expectedDataFileList =
|
|
ImmutableList.of(ProtoConversionUtil.convertDataFile(inlineFile));
|
|
verify(mockMobileDataDownloadManager)
|
|
.importFiles(
|
|
eq(expectedGroupKey),
|
|
eq(1L),
|
|
eq("testvariant"),
|
|
eq(expectedDataFileList),
|
|
eq(inlineFileMap),
|
|
eq(Optional.absent()),
|
|
any());
|
|
}
|
|
|
|
@Test
|
|
public void importFiles_whenFails_returnsFailure() throws Exception {
|
|
String inlineFileUrl = String.format("inlinefile:%s", FILE_CHECKSUM_1);
|
|
DataFile inlineFile =
|
|
DataFile.newBuilder()
|
|
.setFileId(FILE_ID_1)
|
|
.setByteSize(FILE_SIZE_1)
|
|
.setChecksum(FILE_CHECKSUM_1)
|
|
.setUrlToDownload(inlineFileUrl)
|
|
.build();
|
|
ImmutableList<DataFile> updatedDataFileList = ImmutableList.of(inlineFile);
|
|
ImmutableMap<String, FileSource> inlineFileMap =
|
|
ImmutableMap.of(
|
|
FILE_ID_1, FileSource.ofByteString(ByteString.copyFromUtf8("TEST_CONTENT")));
|
|
|
|
// TODO: rely on actual implementation once feature is fully implemented.
|
|
when(mockMobileDataDownloadManager.importFiles(
|
|
any(), anyLong(), any(), any(), any(), any(), any()))
|
|
.thenReturn(Futures.immediateFailedFuture(new Exception("Test failure")));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
// Since we use mocks, just call the method directly, no need to call addFileGroup first
|
|
ExecutionException ex =
|
|
assertThrows(
|
|
ExecutionException.class,
|
|
() ->
|
|
mobileDataDownload
|
|
.importFiles(
|
|
ImportFilesRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setBuildId(1)
|
|
.setVariantId("testvariant")
|
|
.setUpdatedDataFileList(updatedDataFileList)
|
|
.setInlineFileMap(inlineFileMap)
|
|
.build())
|
|
.get());
|
|
assertThat(ex).hasMessageThat().contains("Test failure");
|
|
|
|
// Verify mocks were called
|
|
GroupKey expectedGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.build();
|
|
ImmutableList<MetadataProto.DataFile> expectedDataFileList =
|
|
ImmutableList.of(ProtoConversionUtil.convertDataFile(inlineFile));
|
|
verify(mockMobileDataDownloadManager)
|
|
.importFiles(
|
|
eq(expectedGroupKey),
|
|
eq(1L),
|
|
eq("testvariant"),
|
|
eq(expectedDataFileList),
|
|
eq(inlineFileMap),
|
|
eq(Optional.absent()),
|
|
any());
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroup() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean onCompleteInvoked = new AtomicBoolean();
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroup(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
onCompleteInvoked.set(true);
|
|
assertThat(clientFileGroup.getGroupName())
|
|
.isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage())
|
|
.isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
}
|
|
}))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(onCompleteInvoked.get()).isTrue();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().hasAccount()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroup_failed() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(
|
|
Futures.immediateFailedFuture(
|
|
DownloadException.builder()
|
|
.setDownloadResultCode(DownloadResultCode.UNKNOWN_ERROR)
|
|
.setMessage("Fail to download file group")
|
|
.build()));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean listenerOnFailureInvoked = new AtomicBoolean();
|
|
AtomicBoolean callbackOnFailureInvoked = new AtomicBoolean();
|
|
|
|
ListenableFuture<ClientFileGroup> downloadFuture =
|
|
mobileDataDownload.downloadFileGroup(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {}
|
|
|
|
@Override
|
|
public void onFailure(Throwable t) {
|
|
listenerOnFailureInvoked.set(true);
|
|
}
|
|
}))
|
|
.build());
|
|
|
|
Futures.addCallback(
|
|
downloadFuture,
|
|
new FutureCallback<ClientFileGroup>() {
|
|
@Override
|
|
public void onSuccess(ClientFileGroup result) {}
|
|
|
|
@Override
|
|
public void onFailure(Throwable t) {
|
|
callbackOnFailureInvoked.set(true);
|
|
}
|
|
},
|
|
MoreExecutors.directExecutor());
|
|
|
|
assertThrows(ExecutionException.class, downloadFuture::get);
|
|
DownloadException e = LabsFutures.getFailureCauseAs(downloadFuture, DownloadException.class);
|
|
assertThat(e).hasMessageThat().contains("Fail");
|
|
|
|
assertThat(listenerOnFailureInvoked.get()).isTrue();
|
|
assertThat(callbackOnFailureInvoked.get()).isTrue();
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().hasAccount()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroup_withAccount() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean onCompleteInvoked = new AtomicBoolean();
|
|
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroup(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
onCompleteInvoked.set(true);
|
|
assertThat(clientFileGroup.getGroupName())
|
|
.isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage())
|
|
.isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
}
|
|
}))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(onCompleteInvoked.get()).isTrue();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroup_withVariantId() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setVariantId("en").build();
|
|
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroup(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVariantIdOptional(Optional.of("en"))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getVariantId()).isEqualTo("en");
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
|
|
GroupKey expectedGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setVariantId("en")
|
|
.build();
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(expectedGroupKey);
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), anyBoolean()))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()),
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
CountDownLatch onCompleteLatch = new CountDownLatch(1);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
assertThat(clientFileGroup.getGroupName())
|
|
.isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage())
|
|
.isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
// This is to verify that onComplete is called.
|
|
onCompleteLatch.countDown();
|
|
}
|
|
}))
|
|
.build())
|
|
.get();
|
|
|
|
// Verify that onComplete is called.
|
|
if (!onCompleteLatch.await(LATCH_WAIT_TIME_MS, TimeUnit.MILLISECONDS)) {
|
|
throw new RuntimeException("onComplete is not called");
|
|
}
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().hasAccount()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService_failed() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(
|
|
Futures.immediateFailedFuture(
|
|
DownloadException.builder()
|
|
.setDownloadResultCode(DownloadResultCode.UNKNOWN_ERROR)
|
|
.setMessage("Fail to download file group")
|
|
.build()));
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
expectErrorLogMessage(
|
|
"DownloadListener: onFailure:"
|
|
+ " com.google.android.libraries.mobiledatadownload.DownloadException: Fail to download"
|
|
+ " file group");
|
|
|
|
ListenableFuture<ClientFileGroup> downloadFuture =
|
|
mobileDataDownload.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {}
|
|
}))
|
|
.build());
|
|
|
|
AtomicBoolean onFailureInvoked = new AtomicBoolean();
|
|
Futures.addCallback(
|
|
downloadFuture,
|
|
new FutureCallback<ClientFileGroup>() {
|
|
@Override
|
|
public void onSuccess(ClientFileGroup result) {}
|
|
|
|
@Override
|
|
public void onFailure(Throwable t) {
|
|
onFailureInvoked.set(true);
|
|
}
|
|
},
|
|
MoreExecutors.directExecutor());
|
|
|
|
assertThrows(ExecutionException.class, downloadFuture::get);
|
|
DownloadException e = LabsFutures.getFailureCauseAs(downloadFuture, DownloadException.class);
|
|
assertThat(e).hasMessageThat().contains("Fail");
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
|
|
assertThat(onFailureInvoked.get()).isTrue();
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().hasAccount()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService_withAccount() throws Exception {
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(groupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean onCompleteInvoked = new AtomicBoolean();
|
|
Account account = AccountUtil.create("account-name", "account-type");
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setAccountOptional(Optional.of(account))
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
onCompleteInvoked.set(true);
|
|
assertThat(clientFileGroup.getGroupName())
|
|
.isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage())
|
|
.isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
}
|
|
}))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(onCompleteInvoked.get()).isTrue();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
|
|
assertThat(groupKeyCaptor.getValue().getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(groupKeyCaptor.getValue().getAccount()).isEqualTo(AccountUtil.serialize(account));
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService_withVariantId() throws Exception {
|
|
DataFileGroupInternal dataFileGroup =
|
|
FILE_GROUP_INTERNAL_1.toBuilder().setVariantId("en").build();
|
|
|
|
ArgumentCaptor<GroupKey> pendingGroupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
ArgumentCaptor<GroupKey> groupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
ArgumentCaptor<GroupKey> downloadGroupKeyCaptor = ArgumentCaptor.forClass(GroupKey.class);
|
|
when(mockMobileDataDownloadManager.downloadFileGroup(
|
|
downloadGroupKeyCaptor.capture(), any(), any()))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
dataFileGroup, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(ImmutableMap.of(dataFileGroup.getFile(0), onDeviceUri1)));
|
|
// The order here is important: first mock true and then false.
|
|
// eq(true) returns false, and so if you mock false first, pendingGroupKeyCapture will capture
|
|
// the value of groupKeyCaptor.capture(), which is null.
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.getFileGroup(pendingGroupKeyCaptor.capture(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(dataFileGroup));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setVariantIdOptional(Optional.of("en"))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getVariantId()).isEqualTo("en");
|
|
|
|
verify(mockMobileDataDownloadManager).downloadFileGroup(any(GroupKey.class), any(), any());
|
|
|
|
GroupKey expectedGroupKey =
|
|
GroupKey.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setOwnerPackage(context.getPackageName())
|
|
.setVariantId("en")
|
|
.build();
|
|
assertThat(groupKeyCaptor.getAllValues()).hasSize(1);
|
|
assertThat(groupKeyCaptor.getValue()).isEqualTo(expectedGroupKey);
|
|
assertThat(pendingGroupKeyCaptor.getAllValues()).hasSize(1);
|
|
assertThat(pendingGroupKeyCaptor.getValue()).isEqualTo(expectedGroupKey);
|
|
assertThat(downloadGroupKeyCaptor.getAllValues()).hasSize(1);
|
|
assertThat(downloadGroupKeyCaptor.getValue()).isEqualTo(expectedGroupKey);
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService_whenAlreadyDownloaded() throws Exception {
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
|
|
// Mock situation: no pending group but there is a downloaded group
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(false)))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean onCompleteInvoked = new AtomicBoolean(false);
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
onCompleteInvoked.set(true);
|
|
assertThat(clientFileGroup.getGroupName())
|
|
.isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage())
|
|
.isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
}
|
|
}))
|
|
.build())
|
|
.get();
|
|
|
|
assertThat(onCompleteInvoked.get()).isTrue();
|
|
assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME_1);
|
|
assertThat(clientFileGroup.getOwnerPackage()).isEqualTo(context.getPackageName());
|
|
assertThat(clientFileGroup.getVersionNumber()).isEqualTo(5);
|
|
assertThat(clientFileGroup.getFileCount()).isEqualTo(1);
|
|
assertThat(clientFileGroup.hasAccount()).isFalse();
|
|
|
|
ClientFile clientFile = clientFileGroup.getFileList().get(0);
|
|
assertThat(clientFile.getFileId()).isEqualTo(FILE_ID_1);
|
|
assertThat(clientFile.getFileUri()).isEqualTo(onDeviceUri1.toString());
|
|
|
|
verify(mockMobileDataDownloadManager, times(1)).getFileGroup(any(GroupKey.class), eq(true));
|
|
verify(mockMobileDataDownloadManager, times(1)).getFileGroup(any(GroupKey.class), eq(false));
|
|
verify(mockMobileDataDownloadManager, times(0))
|
|
.downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor)
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
verify(mockDownloadMonitor).removeDownloadListener(eq(FILE_GROUP_NAME_1));
|
|
}
|
|
|
|
@Test
|
|
public void downloadFileGroupWithForegroundService_whenNoVersionFound_fails() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(groupKeyCaptor.capture(), anyBoolean()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.of(mockDownloadMonitor),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
AtomicBoolean onFailureInvoked = new AtomicBoolean(false);
|
|
ListenableFuture<ClientFileGroup> downloadFuture =
|
|
mobileDataDownload.downloadFileGroupWithForegroundService(
|
|
DownloadFileGroupRequest.newBuilder()
|
|
.setGroupName(FILE_GROUP_NAME_1)
|
|
.setListenerOptional(
|
|
Optional.of(
|
|
new DownloadListener() {
|
|
@Override
|
|
public void onProgress(long currentSize) {}
|
|
|
|
@Override
|
|
public void onComplete(ClientFileGroup clientFileGroup) {
|
|
fail("onComplete should not be called");
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(Throwable t) {
|
|
onFailureInvoked.set(true);
|
|
assertThat(t).isInstanceOf(DownloadException.class);
|
|
assertThat(((DownloadException) t).getDownloadResultCode())
|
|
.isEqualTo(DownloadResultCode.GROUP_NOT_FOUND_ERROR);
|
|
}
|
|
}))
|
|
.build());
|
|
|
|
assertThrows(ExecutionException.class, downloadFuture::get);
|
|
|
|
assertThat(onFailureInvoked.get()).isTrue();
|
|
DownloadException e = LabsFutures.getFailureCauseAs(downloadFuture, DownloadException.class);
|
|
assertThat(e.getDownloadResultCode()).isEqualTo(DownloadResultCode.GROUP_NOT_FOUND_ERROR);
|
|
|
|
// Verify did not attempt a download
|
|
verify(mockMobileDataDownloadManager, times(0))
|
|
.downloadFileGroup(any(GroupKey.class), any(), any());
|
|
verify(mockDownloadMonitor, times(0))
|
|
.addDownloadListener(eq(FILE_GROUP_NAME_1), any(DownloadListener.class));
|
|
}
|
|
|
|
@Test
|
|
public void maintenance_success() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.maintenance()).thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.maintenance().get();
|
|
|
|
verify(mockMobileDataDownloadManager).maintenance();
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void maintenance_failure() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.maintenance())
|
|
.thenReturn(Futures.immediateFailedFuture(new IOException("test-failure")));
|
|
|
|
ExecutionException e =
|
|
assertThrows(ExecutionException.class, () -> mobileDataDownload.maintenance().get());
|
|
assertThat(e).hasCauseThat().isInstanceOf(IOException.class);
|
|
assertThat(e).hasCauseThat().hasMessageThat().isEqualTo("test-failure");
|
|
|
|
verify(mockMobileDataDownloadManager).maintenance();
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void collectGarbage_interactionTest() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.removeExpiredGroupsAndFiles())
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.collectGarbage().get();
|
|
|
|
verify(mockMobileDataDownloadManager).removeExpiredGroupsAndFiles();
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicTasks() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
mobileDataDownload.schedulePeriodicTasks();
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CHARGING_PERIODIC_TASK,
|
|
flags.chargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.MAINTENANCE_PERIODIC_TASK,
|
|
flags.maintenanceGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK,
|
|
flags.cellularChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_CONNECTED,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.WIFI_CHARGING_PERIODIC_TASK,
|
|
flags.wifiChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_UNMETERED,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verifyNoMoreInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicTasks_nullTaskScheduler() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
/* taskSchedulerOptional= */ Optional.absent(),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
expectErrorLogMessage(
|
|
"MobileDataDownload: Called schedulePeriodicTasksInternal when taskScheduler is not"
|
|
+ " provided.");
|
|
mobileDataDownload.schedulePeriodicTasks();
|
|
|
|
verifyNoInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicBackgroundTasks() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
mobileDataDownload.schedulePeriodicBackgroundTasks().get();
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CHARGING_PERIODIC_TASK,
|
|
flags.chargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.MAINTENANCE_PERIODIC_TASK,
|
|
flags.maintenanceGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK,
|
|
flags.cellularChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_CONNECTED,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.WIFI_CHARGING_PERIODIC_TASK,
|
|
flags.wifiChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_UNMETERED,
|
|
/* constraintOverrides= */ Optional.absent());
|
|
|
|
verifyNoMoreInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicBackgroundTasks_nullTaskScheduler() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
/* taskSchedulerOptional= */ Optional.absent(),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
expectErrorLogMessage(
|
|
"MobileDataDownload: Called schedulePeriodicTasksInternal when taskScheduler is not"
|
|
+ " provided.");
|
|
mobileDataDownload.schedulePeriodicBackgroundTasks().get();
|
|
|
|
verifyNoInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicBackgroundTasks_withConstraintOverrides() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ConstraintOverrides wifiOverrides =
|
|
ConstraintOverrides.newBuilder()
|
|
.setRequiresCharging(false)
|
|
.setRequiresDeviceIdle(true)
|
|
.build();
|
|
ConstraintOverrides cellularOverrides =
|
|
ConstraintOverrides.newBuilder()
|
|
.setRequiresCharging(true)
|
|
.setRequiresDeviceIdle(false)
|
|
.build();
|
|
|
|
Map<String, ConstraintOverrides> constraintOverridesMap = new HashMap<>();
|
|
constraintOverridesMap.put(TaskScheduler.WIFI_CHARGING_PERIODIC_TASK, wifiOverrides);
|
|
constraintOverridesMap.put(TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK, cellularOverrides);
|
|
|
|
mobileDataDownload.schedulePeriodicBackgroundTasks(Optional.of(constraintOverridesMap)).get();
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CHARGING_PERIODIC_TASK,
|
|
flags.chargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.MAINTENANCE_PERIODIC_TASK,
|
|
flags.maintenanceGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_ANY,
|
|
Optional.absent());
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK,
|
|
flags.cellularChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_CONNECTED,
|
|
Optional.of(cellularOverrides));
|
|
|
|
verify(mockTaskScheduler)
|
|
.schedulePeriodicTask(
|
|
TaskScheduler.WIFI_CHARGING_PERIODIC_TASK,
|
|
flags.wifiChargingGcmTaskPeriod(),
|
|
NetworkState.NETWORK_STATE_UNMETERED,
|
|
Optional.of(wifiOverrides));
|
|
|
|
verifyNoMoreInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void schedulePeriodicBackgroundTasks_nullTaskScheduler_andOverrides() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
/* taskSchedulerOptional= */ Optional.absent(),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
expectErrorLogMessage(
|
|
"MobileDataDownload: Called schedulePeriodicTasksInternal when taskScheduler is not"
|
|
+ " provided.");
|
|
|
|
mobileDataDownload.schedulePeriodicBackgroundTasks(Optional.absent()).get();
|
|
|
|
verifyNoInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void cancelPeriodicBackgroundTasks_nullTaskScheduler() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
/* taskSchedulerOptional= */ Optional.absent(),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.absent() /* foregroundDownloadServiceClassOptional */,
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
mobileDataDownload.cancelPeriodicBackgroundTasks().get();
|
|
|
|
verifyNoInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
@Test
|
|
public void cancelPeriodicBackgroundTasks() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.absent() /* foregroundDownloadServiceClassOptional */,
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
mobileDataDownload.cancelPeriodicBackgroundTasks().get();
|
|
|
|
verify(mockTaskScheduler).cancelPeriodicTask(TaskScheduler.CHARGING_PERIODIC_TASK);
|
|
|
|
verify(mockTaskScheduler).cancelPeriodicTask(TaskScheduler.MAINTENANCE_PERIODIC_TASK);
|
|
|
|
verify(mockTaskScheduler).cancelPeriodicTask(TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK);
|
|
|
|
verify(mockTaskScheduler).cancelPeriodicTask(TaskScheduler.WIFI_CHARGING_PERIODIC_TASK);
|
|
|
|
verifyNoMoreInteractions(mockTaskScheduler);
|
|
}
|
|
|
|
// A helper function to create a DataFilegroup.
|
|
private static DataFileGroup createDataFileGroup(
|
|
String groupName,
|
|
String ownerPackage,
|
|
int versionNumber,
|
|
String[] fileId,
|
|
int[] byteSize,
|
|
String[] checksum,
|
|
String[] url,
|
|
DeviceNetworkPolicy deviceNetworkPolicy) {
|
|
if (fileId.length != byteSize.length
|
|
|| fileId.length != checksum.length
|
|
|| fileId.length != url.length) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
|
|
DataFileGroup.Builder dataFileGroupBuilder =
|
|
DataFileGroup.newBuilder()
|
|
.setGroupName(groupName)
|
|
.setOwnerPackage(ownerPackage)
|
|
.setFileGroupVersionNumber(versionNumber)
|
|
.setDownloadConditions(
|
|
DownloadConditions.newBuilder().setDeviceNetworkPolicy(deviceNetworkPolicy));
|
|
|
|
for (int i = 0; i < fileId.length; ++i) {
|
|
DataFile file =
|
|
DataFile.newBuilder()
|
|
.setFileId(fileId[i])
|
|
.setByteSize(byteSize[i])
|
|
.setChecksum(checksum[i])
|
|
.setUrlToDownload(url[i])
|
|
.build();
|
|
dataFileGroupBuilder.addFile(file);
|
|
}
|
|
|
|
return dataFileGroupBuilder.build();
|
|
}
|
|
|
|
private static DataFileGroupInternal createDataFileGroupInternal(
|
|
String groupName,
|
|
String ownerPackage,
|
|
int versionNumber,
|
|
String[] fileId,
|
|
int[] byteSize,
|
|
String[] checksum,
|
|
String[] url,
|
|
DeviceNetworkPolicy deviceNetworkPolicy) {
|
|
try {
|
|
return ProtoConversionUtil.convert(
|
|
createDataFileGroup(
|
|
groupName,
|
|
ownerPackage,
|
|
versionNumber,
|
|
fileId,
|
|
byteSize,
|
|
checksum,
|
|
url,
|
|
deviceNetworkPolicy));
|
|
} catch (Exception e) {
|
|
// wrap with runtime exception to avoid this method having to declare throws
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_maintenance() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
when(mockMobileDataDownloadManager.maintenance()).thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.MAINTENANCE_PERIODIC_TASK).get();
|
|
verify(mockMobileDataDownloadManager).maintenance();
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_charging() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of(mockFileGroupPopulator),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.verifyAllPendingGroups(any()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockFileGroupPopulator.refreshFileGroups(mobileDataDownload))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.CHARGING_PERIODIC_TASK).get();
|
|
verify(mockFileGroupPopulator).refreshFileGroups(mobileDataDownload);
|
|
verify(mockMobileDataDownloadManager).verifyAllPendingGroups(any());
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_wifi_charging() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of(mockFileGroupPopulator),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockFileGroupPopulator.refreshFileGroups(mobileDataDownload))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.downloadAllPendingGroups(eq(true) /*wifi*/, any()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.WIFI_CHARGING_PERIODIC_TASK).get();
|
|
verify(mockFileGroupPopulator, times(2)).refreshFileGroups(mobileDataDownload);
|
|
verify(mockMobileDataDownloadManager, times(2)).downloadAllPendingGroups(eq(true), any());
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_cellular_charging() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of(mockFileGroupPopulator),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockFileGroupPopulator.refreshFileGroups(mobileDataDownload))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.downloadAllPendingGroups(eq(false) /*wifi*/, any()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK).get();
|
|
verify(mockFileGroupPopulator, times(2)).refreshFileGroups(mobileDataDownload);
|
|
verify(mockMobileDataDownloadManager, times(2)).downloadAllPendingGroups(eq(false), any());
|
|
verifyNoMoreInteractions(mockMobileDataDownloadManager);
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_no_filegroup_populator() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
/* fileGroupPopulatorList= */ ImmutableList.of(),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.verifyAllPendingGroups(any()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
when(mockMobileDataDownloadManager.downloadAllPendingGroups(anyBoolean() /*wifi*/, any()))
|
|
.thenReturn(Futures.immediateFuture(null));
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.CHARGING_PERIODIC_TASK).get();
|
|
verify(mockMobileDataDownloadManager).verifyAllPendingGroups(any());
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.CELLULAR_CHARGING_PERIODIC_TASK).get();
|
|
verify(mockMobileDataDownloadManager, times(2)).downloadAllPendingGroups(eq(false), any());
|
|
|
|
mobileDataDownload.handleTask(TaskScheduler.WIFI_CHARGING_PERIODIC_TASK).get();
|
|
verify(mockMobileDataDownloadManager, times(2)).downloadAllPendingGroups(eq(true), any());
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_invalid_tag() throws Exception {
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of(mockFileGroupPopulator),
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
ExecutionException e =
|
|
assertThrows(
|
|
ExecutionException.class, () -> mobileDataDownload.handleTask("invalid-tag").get());
|
|
assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
|
}
|
|
|
|
@Test
|
|
public void handleTask_onePopulatorFails_continuesToRunOthers() throws Exception {
|
|
FileGroupPopulator failingPopulator =
|
|
(MobileDataDownload unused) ->
|
|
Futures.immediateFailedFuture(new IllegalArgumentException("test"));
|
|
|
|
AtomicBoolean refreshedOneSucceedingPopulator = new AtomicBoolean(false);
|
|
FileGroupPopulator oneSucceedingPopulator =
|
|
(MobileDataDownload unused) -> {
|
|
refreshedOneSucceedingPopulator.set(true);
|
|
return Futures.immediateVoidFuture();
|
|
};
|
|
|
|
AtomicBoolean refreshedAnotherSucceedingPopulator = new AtomicBoolean(false);
|
|
FileGroupPopulator anotherSucceedingPopulator =
|
|
(MobileDataDownload unused) -> {
|
|
refreshedAnotherSucceedingPopulator.set(true);
|
|
return Futures.immediateVoidFuture();
|
|
};
|
|
|
|
// The populators will be executed in this order.
|
|
ImmutableList<FileGroupPopulator> populators =
|
|
ImmutableList.of(failingPopulator, oneSucceedingPopulator, anotherSucceedingPopulator);
|
|
|
|
MobileDataDownload mobileDataDownload =
|
|
new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
populators,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
/* downloadMonitorOptional= */ Optional.absent(),
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
|
|
when(mockMobileDataDownloadManager.verifyAllPendingGroups(any() /* validator */))
|
|
.thenReturn(Futures.immediateVoidFuture());
|
|
when(mockMobileDataDownloadManager.downloadAllPendingGroups(
|
|
anyBoolean() /*wifi*/, any() /* validator */))
|
|
.thenReturn(Futures.immediateVoidFuture());
|
|
|
|
ListenableFuture<Void> handleFuture =
|
|
mobileDataDownload.handleTask(TaskScheduler.WIFI_CHARGING_PERIODIC_TASK);
|
|
assertThat(handleFuture).whenDone().isSuccessful();
|
|
|
|
handleFuture.get();
|
|
assertThat(refreshedOneSucceedingPopulator.get()).isTrue();
|
|
assertThat(refreshedAnotherSucceedingPopulator.get()).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void reportUsage_basic() throws Exception {
|
|
when(mockMobileDataDownloadManager.getFileGroup(any(GroupKey.class), eq(true)))
|
|
.thenReturn(Futures.immediateFuture(FILE_GROUP_INTERNAL_1));
|
|
when(mockMobileDataDownloadManager.getDataFileUris(
|
|
FILE_GROUP_INTERNAL_1, /* verifyIsolatedStructure= */ true))
|
|
.thenReturn(
|
|
Futures.immediateFuture(
|
|
ImmutableMap.of(FILE_GROUP_INTERNAL_1.getFile(0), onDeviceUri1)));
|
|
|
|
MobileDataDownload mobileDataDownload = createDefaultMobileDataDownload();
|
|
|
|
ClientFileGroup clientFileGroup =
|
|
mobileDataDownload
|
|
.getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME_1).build())
|
|
.get();
|
|
|
|
UsageEvent usageEvent =
|
|
UsageEvent.builder()
|
|
.setEventCode(0)
|
|
.setAppVersion(123)
|
|
.setClientFileGroup(clientFileGroup)
|
|
.build();
|
|
mobileDataDownload.reportUsage(usageEvent).get();
|
|
|
|
verify(mockEventLogger).logMddUsageEvent(createFileGroupStats(clientFileGroup), null);
|
|
}
|
|
|
|
private static DataDownloadFileGroupStats createFileGroupStats(ClientFileGroup clientFileGroup) {
|
|
return DataDownloadFileGroupStats.newBuilder()
|
|
.setFileGroupName(clientFileGroup.getGroupName())
|
|
.setOwnerPackage(clientFileGroup.getOwnerPackage())
|
|
.setFileGroupVersionNumber(clientFileGroup.getVersionNumber())
|
|
.setFileCount(clientFileGroup.getFileCount())
|
|
.setVariantId(clientFileGroup.getVariantId())
|
|
.setBuildId(clientFileGroup.getBuildId())
|
|
.build();
|
|
}
|
|
|
|
private MobileDataDownload createDefaultMobileDataDownload() {
|
|
return new MobileDataDownloadImpl(
|
|
context,
|
|
mockEventLogger,
|
|
mockMobileDataDownloadManager,
|
|
controlExecutor,
|
|
ImmutableList.of() /* fileGroupPopulatorList */,
|
|
Optional.of(mockTaskScheduler),
|
|
fileStorage,
|
|
Optional.absent() /* downloadMonitorOptional */,
|
|
Optional.of(this.getClass()), // don't need to use the real foreground download service.
|
|
flags,
|
|
singleFileDownloader,
|
|
Optional.absent() /* customFileGroupValidator */,
|
|
timeSource);
|
|
}
|
|
}
|