1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.libraries.mobiledatadownload; 17 18 import static com.google.android.libraries.mobiledatadownload.TestFileGroupPopulator.FILE_CHECKSUM; 19 import static com.google.android.libraries.mobiledatadownload.TestFileGroupPopulator.FILE_GROUP_NAME; 20 import static com.google.android.libraries.mobiledatadownload.TestFileGroupPopulator.FILE_ID; 21 import static com.google.android.libraries.mobiledatadownload.TestFileGroupPopulator.FILE_SIZE; 22 import static com.google.android.libraries.mobiledatadownload.TestFileGroupPopulator.FILE_URL; 23 import static com.google.android.libraries.mobiledatadownload.testing.MddTestDependencies.DownloaderConfigurationType; 24 import static com.google.android.libraries.mobiledatadownload.testing.MddTestDependencies.ExecutorType; 25 import static com.google.common.truth.Truth.assertThat; 26 import static java.util.concurrent.TimeUnit.SECONDS; 27 import static org.junit.Assert.assertThrows; 28 29 import android.accounts.Account; 30 import android.content.Context; 31 import android.net.Uri; 32 import android.util.Log; 33 import androidx.test.core.app.ApplicationProvider; 34 import com.google.android.libraries.mobiledatadownload.account.AccountUtil; 35 import com.google.android.libraries.mobiledatadownload.downloader.FileDownloader; 36 import com.google.android.libraries.mobiledatadownload.file.SynchronousFileStorage; 37 import com.google.android.libraries.mobiledatadownload.file.backends.AndroidFileBackend; 38 import com.google.android.libraries.mobiledatadownload.file.backends.JavaFileBackend; 39 import com.google.android.libraries.mobiledatadownload.file.transforms.CompressTransform; 40 import com.google.android.libraries.mobiledatadownload.monitor.DownloadProgressMonitor; 41 import com.google.android.libraries.mobiledatadownload.monitor.NetworkUsageMonitor; 42 import com.google.android.libraries.mobiledatadownload.testing.BlockingFileDownloader; 43 import com.google.android.libraries.mobiledatadownload.testing.MddTestDependencies; 44 import com.google.android.libraries.mobiledatadownload.testing.TestFileDownloader; 45 import com.google.android.libraries.mobiledatadownload.testing.TestFlags; 46 import com.google.common.base.Optional; 47 import com.google.common.base.Supplier; 48 import com.google.common.collect.ImmutableList; 49 import com.google.common.util.concurrent.Futures; 50 import com.google.common.util.concurrent.ListenableFuture; 51 import com.google.common.util.concurrent.ListeningExecutorService; 52 import com.google.common.util.concurrent.ListeningScheduledExecutorService; 53 import com.google.common.util.concurrent.MoreExecutors; 54 import com.google.mobiledatadownload.ClientConfigProto.ClientFile; 55 import com.google.mobiledatadownload.ClientConfigProto.ClientFileGroup; 56 import com.google.mobiledatadownload.DownloadConfigProto.DataFile; 57 import com.google.mobiledatadownload.DownloadConfigProto.DataFileGroup; 58 import com.google.mobiledatadownload.DownloadConfigProto.DownloadConditions.DeviceNetworkPolicy; 59 import com.google.mobiledatadownload.TransformProto; 60 import com.google.mobiledatadownload.TransformProto.Transform; 61 import com.google.mobiledatadownload.TransformProto.Transforms; 62 import com.google.testing.junit.testparameterinjector.TestParameter; 63 import com.google.testing.junit.testparameterinjector.TestParameterInjector; 64 import java.util.ArrayList; 65 import java.util.List; 66 import java.util.concurrent.ExecutionException; 67 import java.util.concurrent.Executors; 68 import org.junit.Before; 69 import org.junit.Rule; 70 import org.junit.Test; 71 import org.junit.runner.RunWith; 72 import org.mockito.Mock; 73 import org.mockito.junit.MockitoJUnit; 74 import org.mockito.junit.MockitoRule; 75 76 /** 77 * Integration Tests that relate to {@link MobileDataDownload#downloadFileGroup}. 78 * 79 * <p>NOTE: Any tests related to cancellation should be added to {@link 80 * DownloadFileGroupCancellationIntegrationTest} instead. 81 */ 82 @RunWith(TestParameterInjector.class) 83 public class DownloadFileGroupIntegrationTest { 84 85 private static final String TAG = "DownloadFileGroupIntegrationTest"; 86 private static final int MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS = 60; 87 private static final int MAX_MULTI_MDD_API_WAIT_TIME_SECS = 120; 88 private static final long MAX_MDD_API_WAIT_TIME_SECS = 5L; 89 90 private static final ListeningScheduledExecutorService DOWNLOAD_EXECUTOR = 91 MoreExecutors.listeningDecorator(Executors.newScheduledThreadPool(4)); 92 93 private static final String FILE_GROUP_NAME_INSECURE_URL = "test-group-insecure-url"; 94 private static final String FILE_GROUP_NAME_MULTIPLE_FILES = "test-group-multiple-files"; 95 96 private static final String FILE_ID_1 = "test-file-1"; 97 private static final String FILE_ID_2 = "test-file-2"; 98 private static final String FILE_CHECKSUM_1 = "a1cba9d87b1440f41ce9e7da38c43e1f6bd7d5df"; 99 private static final String FILE_CHECKSUM_2 = "cb2459d9f1b508993aba36a5ffd942a7e0d49ed6"; 100 private static final String FILE_NOT_EXIST_URL = 101 "https://www.gstatic.com/icing/idd/notexist/file.txt"; 102 103 private static final String TEST_DATA_RELATIVE_PATH = 104 "third_party/java_src/android_libs/mobiledatadownload/javatests/com/google/android/libraries/mobiledatadownload/testdata/"; 105 106 private static final String TEST_DATA_URL = "https://test.url/full_file.txt"; 107 private static final String TEST_DATA_CHECKSUM = "0c4f1e55c4ec28d0305c5cfde8610b7e6e9f7d9a"; 108 private static final int TEST_DATA_BYTE_SIZE = 110; 109 110 private static final String TEST_DATA_COMPRESS_URL = "https://test.url/full_file.zlib"; 111 private static final String TEST_DATA_COMPRESS_CHECKSUM = 112 "cbffcf480fd52a3c6bf9d21206d36f0a714bb97a"; 113 private static final int TEST_DATA_COMPRESS_BYTE_SIZE = 92; 114 115 private static final String VARIANT_1 = "test-variant-1"; 116 private static final String VARIANT_2 = "test-variant-2"; 117 118 private static final Account ACCOUNT_1 = AccountUtil.create("account-name-1", "account-type"); 119 private static final Account ACCOUNT_2 = AccountUtil.create("account-name-2", "account-type"); 120 121 private static final Context context = ApplicationProvider.getApplicationContext(); 122 123 @Mock private TaskScheduler mockTaskScheduler; 124 @Mock private NetworkUsageMonitor mockNetworkUsageMonitor; 125 @Mock private DownloadProgressMonitor mockDownloadProgressMonitor; 126 127 private SynchronousFileStorage fileStorage; 128 private ListeningExecutorService controlExecutor; 129 130 private final TestFlags flags = new TestFlags(); 131 132 @Rule(order = 1) 133 public final MockitoRule mocks = MockitoJUnit.rule(); 134 135 @TestParameter ExecutorType controlExecutorType; 136 137 @Before setUp()138 public void setUp() throws Exception { 139 140 fileStorage = 141 new SynchronousFileStorage( 142 /* backends= */ ImmutableList.of( 143 AndroidFileBackend.builder(context).build(), new JavaFileBackend()), 144 /* transforms= */ ImmutableList.of(new CompressTransform()), 145 /* monitors= */ ImmutableList.of(mockNetworkUsageMonitor, mockDownloadProgressMonitor)); 146 147 controlExecutor = controlExecutorType.executor(); 148 } 149 150 @Test downloadAndRead( @estParameter DownloaderConfigurationType downloaderConfigurationType)151 public void downloadAndRead( 152 @TestParameter DownloaderConfigurationType downloaderConfigurationType) throws Exception { 153 Optional<String> instanceId = Optional.of(MddTestDependencies.randomInstanceId()); 154 TestFileGroupPopulator testFileGroupPopulator = new TestFileGroupPopulator(context); 155 MobileDataDownload mobileDataDownload = 156 builderForTest() 157 .setInstanceIdOptional(instanceId) 158 .setFileDownloaderSupplier( 159 downloaderConfigurationType.fileDownloaderSupplier( 160 context, 161 controlExecutor, 162 DOWNLOAD_EXECUTOR, 163 fileStorage, 164 flags, 165 Optional.of(mockDownloadProgressMonitor), 166 instanceId)) 167 .addFileGroupPopulator(testFileGroupPopulator) 168 .build(); 169 170 testFileGroupPopulator 171 .refreshFileGroups(mobileDataDownload) 172 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 173 174 mobileDataDownload 175 .downloadFileGroup( 176 DownloadFileGroupRequest.newBuilder() 177 .setGroupName(FILE_GROUP_NAME) 178 .setListenerOptional( 179 Optional.of( 180 new DownloadListener() { 181 @Override 182 public void onProgress(long currentSize) { 183 Log.i(TAG, "onProgress " + currentSize); 184 } 185 186 @Override 187 public void onComplete(ClientFileGroup clientFileGroup) { 188 Log.i(TAG, "onComplete " + clientFileGroup.getGroupName()); 189 } 190 })) 191 .build()) 192 .get(MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS, SECONDS); 193 194 ClientFileGroup clientFileGroup = 195 mobileDataDownload 196 .getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME).build()) 197 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 198 199 assertThat(clientFileGroup).isNotNull(); 200 assertThat(clientFileGroup.getGroupName()).isEqualTo(FILE_GROUP_NAME); 201 assertThat(clientFileGroup.getFileCount()).isEqualTo(1); 202 203 ClientFile clientFile = clientFileGroup.getFileList().get(0); 204 assertThat(clientFile.getFileId()).isEqualTo(FILE_ID); 205 Uri androidUri = Uri.parse(clientFile.getFileUri()); 206 assertThat(fileStorage.fileSize(androidUri)).isEqualTo(FILE_SIZE); 207 208 mobileDataDownload.clear().get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 209 210 switch (downloaderConfigurationType) { 211 case V2_PLATFORM: 212 // No-op 213 } 214 } 215 216 @Test downloadFailed()217 public void downloadFailed() throws Exception { 218 // NOTE: The test failures here are not network stack dependent, so there's 219 // no need to parameterize this test for different network stacks. 220 Optional<String> instanceId = Optional.of(MddTestDependencies.randomInstanceId()); 221 MobileDataDownload mobileDataDownload = 222 builderForTest() 223 .setInstanceIdOptional(instanceId) 224 .setFileDownloaderSupplier( 225 DownloaderConfigurationType.V2_PLATFORM.fileDownloaderSupplier( 226 context, 227 controlExecutor, 228 DOWNLOAD_EXECUTOR, 229 fileStorage, 230 flags, 231 Optional.of(mockDownloadProgressMonitor), 232 instanceId)) 233 .build(); 234 235 // The data file group has a file with insecure url. 236 DataFileGroup groupWithInsecureUrl = 237 TestFileGroupPopulator.createDataFileGroup( 238 FILE_GROUP_NAME_INSECURE_URL, 239 context.getPackageName(), 240 new String[] {FILE_ID}, 241 new int[] {FILE_SIZE}, 242 new String[] {FILE_CHECKSUM}, 243 // Make the url insecure. This would lead to download failure. 244 new String[] {FILE_URL.replace("https", "http")}, 245 DeviceNetworkPolicy.DOWNLOAD_ON_ANY_NETWORK); 246 247 // The data file group has a file with non-existent url, and a file with insecure url. 248 DataFileGroup groupWithMultipleFiles = 249 TestFileGroupPopulator.createDataFileGroup( 250 FILE_GROUP_NAME_MULTIPLE_FILES, 251 context.getPackageName(), 252 new String[] {FILE_ID_1, FILE_ID_2}, 253 new int[] {FILE_SIZE, FILE_SIZE}, 254 new String[] {FILE_CHECKSUM_1, FILE_CHECKSUM_2}, 255 // The first file url doesn't exist and the second file url is insecure. 256 new String[] {FILE_NOT_EXIST_URL, FILE_URL.replace("https", "http")}, 257 DeviceNetworkPolicy.DOWNLOAD_ON_ANY_NETWORK); 258 259 assertThat( 260 mobileDataDownload 261 .addFileGroup( 262 AddFileGroupRequest.newBuilder().setDataFileGroup(groupWithInsecureUrl).build()) 263 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS)) 264 .isTrue(); 265 266 assertThat( 267 mobileDataDownload 268 .addFileGroup( 269 AddFileGroupRequest.newBuilder() 270 .setDataFileGroup(groupWithMultipleFiles) 271 .build()) 272 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS)) 273 .isTrue(); 274 275 ExecutionException exception = 276 assertThrows( 277 ExecutionException.class, 278 () -> 279 mobileDataDownload 280 .downloadFileGroup( 281 DownloadFileGroupRequest.newBuilder() 282 .setGroupName(FILE_GROUP_NAME_INSECURE_URL) 283 .build()) 284 .get(MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS, SECONDS)); 285 assertThat(exception).hasCauseThat().isInstanceOf(AggregateException.class); 286 AggregateException cause = (AggregateException) exception.getCause(); 287 assertThat(cause).isNotNull(); 288 ImmutableList<Throwable> failures = cause.getFailures(); 289 assertThat(failures).hasSize(1); 290 assertThat(failures.get(0)).isInstanceOf(DownloadException.class); 291 assertThat(failures.get(0)).hasMessageThat().contains("INSECURE_URL_ERROR"); 292 293 ExecutionException exception2 = 294 assertThrows( 295 ExecutionException.class, 296 () -> 297 mobileDataDownload 298 .downloadFileGroup( 299 DownloadFileGroupRequest.newBuilder() 300 .setGroupName(FILE_GROUP_NAME_MULTIPLE_FILES) 301 .build()) 302 .get(MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS, SECONDS)); 303 assertThat(exception2).hasCauseThat().isInstanceOf(AggregateException.class); 304 AggregateException cause2 = (AggregateException) exception2.getCause(); 305 assertThat(cause2).isNotNull(); 306 ImmutableList<Throwable> failures2 = cause2.getFailures(); 307 assertThat(failures2).hasSize(2); 308 assertThat(failures2.get(0)).isInstanceOf(DownloadException.class); 309 assertThat(failures2.get(0)) 310 .hasCauseThat() 311 .hasMessageThat() 312 .containsMatch("httpStatusCode=404"); 313 assertThat(failures2.get(1)).isInstanceOf(DownloadException.class); 314 assertThat(failures2.get(1)).hasMessageThat().contains("INSECURE_URL_ERROR"); 315 316 AggregateException exception3 = 317 assertThrows( 318 AggregateException.class, 319 () -> { 320 try { 321 ListenableFuture<ClientFileGroup> downloadFuture1 = 322 mobileDataDownload.downloadFileGroup( 323 DownloadFileGroupRequest.newBuilder() 324 .setGroupName(FILE_GROUP_NAME_MULTIPLE_FILES) 325 .build()); 326 ListenableFuture<ClientFileGroup> downloadFuture2 = 327 mobileDataDownload.downloadFileGroup( 328 DownloadFileGroupRequest.newBuilder() 329 .setGroupName(FILE_GROUP_NAME_INSECURE_URL) 330 .build()); 331 332 Futures.successfulAsList(downloadFuture1, downloadFuture2) 333 .get(MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS, SECONDS); 334 335 AggregateException.throwIfFailed( 336 ImmutableList.of(downloadFuture1, downloadFuture2), 337 "Expected download failures"); 338 } catch (ExecutionException e) { 339 throw e; 340 } 341 }); 342 assertThat(exception3.getFailures()).hasSize(2); 343 } 344 345 @Test removePartialDownloadThenDownloadAgain( @estParameter DownloaderConfigurationType downloaderConfigurationType)346 public void removePartialDownloadThenDownloadAgain( 347 @TestParameter DownloaderConfigurationType downloaderConfigurationType) throws Exception { 348 Optional<String> instanceId = Optional.of(MddTestDependencies.randomInstanceId()); 349 350 Supplier<FileDownloader> fileDownloaderSupplier = 351 downloaderConfigurationType.fileDownloaderSupplier( 352 context, 353 controlExecutor, 354 DOWNLOAD_EXECUTOR, 355 fileStorage, 356 flags, 357 Optional.of(mockDownloadProgressMonitor), 358 instanceId); 359 BlockingFileDownloader blockingFileDownloader = 360 new BlockingFileDownloader(DOWNLOAD_EXECUTOR, fileDownloaderSupplier.get()); 361 362 MobileDataDownload mobileDataDownload = 363 builderForTest() 364 .setInstanceIdOptional(instanceId) 365 .setFileDownloaderSupplier(() -> blockingFileDownloader) 366 .build(); 367 368 mobileDataDownload.clear().get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 369 370 // Add the filegroup, start downloading, then cancel while in progress. 371 TestFileGroupPopulator testFileGroupPopulator = new TestFileGroupPopulator(context); 372 testFileGroupPopulator 373 .refreshFileGroups(mobileDataDownload) 374 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 375 376 ListenableFuture<ClientFileGroup> downloadFuture = 377 mobileDataDownload.downloadFileGroup( 378 DownloadFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME).build()); 379 380 blockingFileDownloader.finishDownloading(); // Unblocks blockingFileDownloader 381 blockingFileDownloader.waitForDelegateStarted(); // Waits until offroadDownloader starts 382 383 // NOTE: add a little wait to allow Downloader's listeners to run. 384 Thread.sleep(/* millis= */ 200); 385 386 downloadFuture.cancel(true /* may interrupt */); 387 388 // NOTE: add a little wait to allow Downloader's listeners to run. 389 Thread.sleep(/* millis= */ 200); 390 391 // Remove the filegroup. 392 ListenableFuture<Boolean> removeFuture = 393 mobileDataDownload.removeFileGroup( 394 RemoveFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME).build()); 395 removeFuture.get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 396 397 // Add then try to download again. 398 blockingFileDownloader.resetState(); 399 blockingFileDownloader.finishDownloading(); // Unblocks blockingFileDownloader 400 401 testFileGroupPopulator 402 .refreshFileGroups(mobileDataDownload) 403 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 404 405 downloadFuture = 406 mobileDataDownload.downloadFileGroup( 407 DownloadFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME).build()); 408 409 downloadFuture.get(MAX_DOWNLOAD_FILE_GROUP_WAIT_TIME_SECS, SECONDS); 410 411 // The file should have downloaded as expected. 412 ClientFileGroup clientFileGroup = 413 mobileDataDownload 414 .getFileGroup(GetFileGroupRequest.newBuilder().setGroupName(FILE_GROUP_NAME).build()) 415 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 416 417 assertThat(clientFileGroup).isNotNull(); 418 assertThat(clientFileGroup.getFileCount()).isEqualTo(1); 419 Uri androidUri = Uri.parse(clientFileGroup.getFileList().get(0).getFileUri()); 420 assertThat(fileStorage.fileSize(androidUri)).isEqualTo(FILE_SIZE); 421 } 422 423 @Test downloadDifferentGroupsWithSameFileTest()424 public void downloadDifferentGroupsWithSameFileTest() throws Exception { 425 Optional<String> instanceId = Optional.of(MddTestDependencies.randomInstanceId()); 426 MobileDataDownload mobileDataDownload = 427 builderForTest() 428 .setInstanceIdOptional(instanceId) 429 .setFileDownloaderSupplier( 430 () -> 431 new TestFileDownloader(TEST_DATA_RELATIVE_PATH, fileStorage, DOWNLOAD_EXECUTOR)) 432 .build(); 433 434 DataFile.Builder dataFileBuilder = 435 DataFile.newBuilder() 436 .setUrlToDownload(TEST_DATA_URL) 437 .setChecksum(TEST_DATA_CHECKSUM) 438 .setByteSize(TEST_DATA_BYTE_SIZE); 439 DataFileGroup.Builder groupBuilder = DataFileGroup.newBuilder(); 440 441 // Add all groups concurrently 442 ArrayList<ListenableFuture<Boolean>> addFutures = new ArrayList<>(); 443 for (int i = 0; i < 50; i++) { 444 String groupName = String.format("group%d", i); 445 String fileId = String.format("group%d_file", i); 446 447 DataFile file = dataFileBuilder.setFileId(fileId).build(); 448 DataFileGroup group = 449 DataFileGroup.newBuilder().setGroupName(groupName).addFile(file).build(); 450 451 addFutures.add( 452 mobileDataDownload.addFileGroup( 453 AddFileGroupRequest.newBuilder().setDataFileGroup(group).build())); 454 } 455 Futures.allAsList(addFutures).get(MAX_MULTI_MDD_API_WAIT_TIME_SECS, SECONDS); 456 457 // Start all downloads concurrently 458 ArrayList<ListenableFuture<ClientFileGroup>> downloadFutures = new ArrayList<>(); 459 for (int i = 0; i < 50; i++) { 460 String groupName = String.format("group%d", i); 461 462 downloadFutures.add( 463 mobileDataDownload.downloadFileGroup( 464 DownloadFileGroupRequest.newBuilder().setGroupName(groupName).build())); 465 } 466 List<ClientFileGroup> groups = 467 Futures.allAsList(downloadFutures).get(MAX_MULTI_MDD_API_WAIT_TIME_SECS, SECONDS); 468 469 assertThat(groups).doesNotContain(null); 470 } 471 472 @Test concurrentDownloads_withSameFile_withDifferentDownloadTransforms_completes( @estParameter boolean enableDedupByFileKey)473 public void concurrentDownloads_withSameFile_withDifferentDownloadTransforms_completes( 474 @TestParameter boolean enableDedupByFileKey) throws Exception { 475 flags.enableFileDownloadDedupByFileKey = Optional.of(enableDedupByFileKey); 476 477 Optional<String> instanceId = Optional.of(MddTestDependencies.randomInstanceId()); 478 MobileDataDownload mobileDataDownload = 479 builderForTest() 480 .setInstanceIdOptional(instanceId) 481 .setFileDownloaderSupplier( 482 () -> 483 new TestFileDownloader(TEST_DATA_RELATIVE_PATH, fileStorage, DOWNLOAD_EXECUTOR)) 484 .build(); 485 486 // Create two groups which share the same file, but have different download transforms 487 DataFileGroup groupWithoutTransform = 488 DataFileGroup.newBuilder() 489 .setGroupName("groupWithoutTransform") 490 .addFile( 491 DataFile.newBuilder() 492 .setFileId("file_no_transform") 493 .setUrlToDownload(TEST_DATA_URL) 494 .setChecksum(TEST_DATA_CHECKSUM) 495 .setByteSize(TEST_DATA_BYTE_SIZE)) 496 .build(); 497 498 DataFileGroup groupWithTransform = 499 DataFileGroup.newBuilder() 500 .setGroupName("groupWithTransform") 501 .addFile( 502 DataFile.newBuilder() 503 .setFileId("file_no_transform") 504 .setUrlToDownload(TEST_DATA_COMPRESS_URL) 505 .setChecksum(TEST_DATA_CHECKSUM) 506 .setByteSize(TEST_DATA_BYTE_SIZE) 507 .setDownloadedFileChecksum(TEST_DATA_COMPRESS_CHECKSUM) 508 .setDownloadedFileByteSize(TEST_DATA_COMPRESS_BYTE_SIZE) 509 .setDownloadTransforms( 510 Transforms.newBuilder() 511 .addTransform( 512 Transform.newBuilder() 513 .setCompress( 514 TransformProto.CompressTransform.getDefaultInstance()) 515 .build()) 516 .build()) 517 .build()) 518 .build(); 519 520 // Add both groups, then attempt to download both concurrently 521 mobileDataDownload 522 .addFileGroup( 523 AddFileGroupRequest.newBuilder().setDataFileGroup(groupWithoutTransform).build()) 524 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 525 mobileDataDownload 526 .addFileGroup(AddFileGroupRequest.newBuilder().setDataFileGroup(groupWithTransform).build()) 527 .get(MAX_MDD_API_WAIT_TIME_SECS, SECONDS); 528 529 ListenableFuture<ClientFileGroup> downloadWithoutTransform = 530 mobileDataDownload.downloadFileGroup( 531 DownloadFileGroupRequest.newBuilder().setGroupName("groupWithoutTransform").build()); 532 ListenableFuture<ClientFileGroup> downloadWithTransform = 533 mobileDataDownload.downloadFileGroup( 534 DownloadFileGroupRequest.newBuilder().setGroupName("groupWithTransform").build()); 535 536 List<ClientFileGroup> downloadedGroups = 537 Futures.allAsList(ImmutableList.of(downloadWithoutTransform, downloadWithTransform)) 538 .get(MAX_MULTI_MDD_API_WAIT_TIME_SECS, SECONDS); 539 540 // Both groups are downloaded and both files point to the same on-device uri. 541 assertThat(downloadedGroups).doesNotContain(null); 542 assertThat(downloadedGroups.get(0).getFile(0).getFileUri()) 543 .isEqualTo(downloadedGroups.get(1).getFile(0).getFileUri()); 544 } 545 546 /** 547 * Returns MDD Builder with common dependencies set -- additional dependencies are added in each 548 * test as needed. 549 */ builderForTest()550 private MobileDataDownloadBuilder builderForTest() { 551 552 return MobileDataDownloadBuilder.newBuilder() 553 .setContext(context) 554 .setControlExecutor(controlExecutor) 555 .setFileStorage(fileStorage) 556 .setTaskScheduler(Optional.of(mockTaskScheduler)) 557 .setDeltaDecoderOptional(Optional.absent()) 558 .setNetworkUsageMonitor(mockNetworkUsageMonitor) 559 .setDownloadMonitorOptional(Optional.of(mockDownloadProgressMonitor)) 560 .setFlagsOptional(Optional.of(flags)); 561 } 562 } 563