• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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