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.lite; 17 18 import static com.google.android.libraries.mobiledatadownload.lite.DownloadProgressMonitor.BUFFERED_TIME_MS; 19 import static com.google.common.truth.Truth.assertThat; 20 import static java.util.concurrent.TimeUnit.MILLISECONDS; 21 import static org.mockito.Mockito.verify; 22 import static org.mockito.Mockito.verifyNoInteractions; 23 import static org.mockito.Mockito.verifyNoMoreInteractions; 24 25 import android.net.Uri; 26 import com.google.android.libraries.mobiledatadownload.file.spi.Monitor.OutputMonitor; 27 import com.google.android.libraries.mobiledatadownload.testing.FakeTimeSource; 28 import com.google.common.util.concurrent.MoreExecutors; 29 import java.util.concurrent.Executor; 30 import org.junit.Before; 31 import org.junit.Rule; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.mockito.Mock; 35 import org.mockito.junit.MockitoJUnit; 36 import org.mockito.junit.MockitoRule; 37 import org.robolectric.RobolectricTestRunner; 38 39 @RunWith(RobolectricTestRunner.class) 40 public class DownloadProgressMonitorTest { 41 42 @Rule public final MockitoRule mocks = MockitoJUnit.rule(); 43 44 // Use directExecutor to ensure the order of test verification. 45 private static final Executor CONTROL_EXECUTOR = MoreExecutors.directExecutor(); 46 47 private static final String FILE_URI_1 = 48 "android://com.google.android.gms/files/datadownload/shared/public/file_1"; 49 50 // Note: We can't make those android uris static variable since the Uri.parse will fail 51 // with initialization. 52 private final Uri uri1 = Uri.parse(FILE_URI_1); 53 54 private static final String FILE_URI_2 = 55 "android://com.google.android.gms/files/datadownload/shared/public/file_2"; 56 private final Uri uri2 = Uri.parse(FILE_URI_2); 57 58 private static final String FILE_URI_3 = 59 "android://com.google.android.gms/files/datadownload/shared/public/file_3"; 60 private final Uri uri3 = Uri.parse(FILE_URI_3); 61 62 private DownloadProgressMonitor downloadMonitor; 63 private final FakeTimeSource clock = new FakeTimeSource(); 64 65 @Mock private DownloadListener mockDownloadListener1; 66 @Mock private DownloadListener mockDownloadListener2; 67 68 @Before setUp()69 public void setUp() throws Exception { 70 downloadMonitor = DownloadProgressMonitor.create(clock, CONTROL_EXECUTOR); 71 } 72 73 @Test bytesWritten_cleanSlate()74 public void bytesWritten_cleanSlate() { 75 downloadMonitor.addDownloadListener(uri1, mockDownloadListener1); 76 downloadMonitor.addDownloadListener(uri2, mockDownloadListener2); 77 78 OutputMonitor outputMonitor1 = downloadMonitor.monitorWrite(uri1); 79 OutputMonitor outputMonitor2 = downloadMonitor.monitorWrite(uri1); 80 OutputMonitor outputMonitor3 = downloadMonitor.monitorWrite(uri3); 81 82 // outputMonitor1 is same as outputMonitor2 since they both monitor for uri1. 83 assertThat(outputMonitor1).isSameInstanceAs(outputMonitor2); 84 assertThat(outputMonitor1).isNotSameInstanceAs(outputMonitor3); 85 86 // The 1st bytesWritten was buffered. 87 outputMonitor1.bytesWritten(new byte[1], 0, 1); 88 verifyNoInteractions(mockDownloadListener1); 89 90 // Now the buffered time passed. 91 clock.advance(BUFFERED_TIME_MS + 100, MILLISECONDS); 92 93 // The 2nd bytesWritten now triggered onProgress. 94 outputMonitor1.bytesWritten(new byte[1], 1, 2); 95 // 1 (first bytesWritten) + 2 (2nd bytesWritten) 96 verify(mockDownloadListener1).onProgress(1 + 2); 97 98 // The 3rd bytesWritten was buffered 99 outputMonitor1.bytesWritten(new byte[1], 3, 4); 100 verifyNoMoreInteractions(mockDownloadListener1); 101 102 // Now the buffered time passed again. 103 clock.advance(BUFFERED_TIME_MS + 100, MILLISECONDS); 104 105 // The 4th bytesWritten now triggered onProgress. 106 outputMonitor1.bytesWritten(new byte[1], 7, 8); 107 verify(mockDownloadListener1).onProgress(1 + 2 + 4 + 8); 108 109 // No bytes were downloaded for FileGroup2. 110 verifyNoInteractions(mockDownloadListener2); 111 } 112 113 @Test bytesWritten_addAndRemoveDownloadListener()114 public void bytesWritten_addAndRemoveDownloadListener() { 115 116 // There is no download listener for uri1. 117 assertThat(downloadMonitor.monitorWrite(uri1)).isNull(); 118 119 // Adding a listener now. 120 downloadMonitor.addDownloadListener(uri1, mockDownloadListener1); 121 122 // Removing the listener. 123 downloadMonitor.removeDownloadListener(uri1); 124 assertThat(downloadMonitor.monitorWrite(uri1)).isNull(); 125 } 126 127 @Test downloaderLifecycleCallback()128 public void downloaderLifecycleCallback() { 129 downloadMonitor.addDownloadListener(uri1, mockDownloadListener1); 130 downloadMonitor.addDownloadListener(uri2, mockDownloadListener2); 131 downloadMonitor.pausedForConnectivity(); 132 verify(mockDownloadListener1).onPausedForConnectivity(); 133 verify(mockDownloadListener2).onPausedForConnectivity(); 134 } 135 } 136