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.downloader; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.mockito.Mockito.any; 20 import static org.mockito.Mockito.verify; 21 import static org.mockito.Mockito.verifyNoMoreInteractions; 22 import static org.mockito.Mockito.when; 23 24 import android.net.Uri; 25 import androidx.test.ext.junit.runners.AndroidJUnit4; 26 import com.google.common.util.concurrent.ListenableFuture; 27 import com.google.common.util.concurrent.SettableFuture; 28 import org.junit.Before; 29 import org.junit.Rule; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 import org.mockito.Mock; 33 import org.mockito.junit.MockitoJUnit; 34 import org.mockito.junit.MockitoRule; 35 36 @RunWith(AndroidJUnit4.class) 37 public final class MultiSchemeFileDownloaderTest { 38 39 @Rule public final MockitoRule mocks = MockitoJUnit.rule(); 40 41 @Mock FileDownloader mockStandardDownloader; 42 SettableFuture<Void> mockStandardDownloaderDownloadFuture = SettableFuture.create(); 43 SettableFuture<CheckContentChangeResponse> mockStandardDownloaderIsContentChangedFuture = 44 SettableFuture.create(); 45 46 @Mock FileDownloader mockPirDownloader; 47 SettableFuture<Void> mockPirDownloaderDownloadFuture = SettableFuture.create(); 48 SettableFuture<CheckContentChangeResponse> mockPirDownloaderIsContentChangedFuture = 49 SettableFuture.create(); 50 51 MultiSchemeFileDownloader downloader; 52 53 @Before setUp()54 public void setUp() { 55 56 when(mockStandardDownloader.startDownloading(any())) 57 .thenReturn(mockStandardDownloaderDownloadFuture); 58 when(mockStandardDownloader.isContentChanged(any())) 59 .thenReturn(mockStandardDownloaderIsContentChangedFuture); 60 when(mockPirDownloader.startDownloading(any())).thenReturn(mockPirDownloaderDownloadFuture); 61 when(mockPirDownloader.isContentChanged(any())) 62 .thenReturn(mockPirDownloaderIsContentChangedFuture); 63 64 downloader = 65 MultiSchemeFileDownloader.builder() 66 .addScheme("http", mockStandardDownloader) 67 .addScheme("https", mockStandardDownloader) 68 .addScheme("pir", mockPirDownloader) 69 .build(); 70 } 71 72 @Test getScheme_worksForHttp()73 public void getScheme_worksForHttp() throws Exception { 74 assertThat(MultiSchemeFileDownloader.getScheme("http://www.google.com")).isEqualTo("http"); 75 } 76 77 @Test getScheme_worksForHttps()78 public void getScheme_worksForHttps() throws Exception { 79 assertThat(MultiSchemeFileDownloader.getScheme("https://www.google.com")).isEqualTo("https"); 80 } 81 82 @Test getScheme_worksForFile()83 public void getScheme_worksForFile() throws Exception { 84 assertThat(MultiSchemeFileDownloader.getScheme("file:///localhost/bar")).isEqualTo("file"); 85 } 86 87 @Test getScheme_worksForData()88 public void getScheme_worksForData() throws Exception { 89 String url = "data:;charset=utf-8;base64,SGVsbG8gYW5kcm9pZCE="; 90 assertThat(MultiSchemeFileDownloader.getScheme(url)).isEqualTo("data"); 91 } 92 93 @Test getScheme_worksForPir()94 public void getScheme_worksForPir() throws Exception { 95 String url = "pir://example.com:1234/database/version/3"; 96 assertThat(MultiSchemeFileDownloader.getScheme(url)).isEqualTo("pir"); 97 } 98 99 @Test startDownloading_delegatesCorrectly_http()100 public void startDownloading_delegatesCorrectly_http() throws Exception { 101 DownloadRequest downloadRequest = 102 DownloadRequest.newBuilder() 103 .setUrlToDownload("http://www.google.com") 104 .setFileUri(Uri.parse("file://dev/null")) 105 .setDownloadConstraints(DownloadConstraints.NONE) 106 .build(); 107 ListenableFuture<Void> future = downloader.startDownloading(downloadRequest); 108 109 verify(mockStandardDownloader).startDownloading(downloadRequest); 110 verifyNoMoreInteractions(mockStandardDownloader); 111 verifyNoMoreInteractions(mockPirDownloader); 112 assertThat(future.isDone()).isFalse(); 113 114 // Make sure we actually got (a view of) the correct future. 115 mockStandardDownloaderDownloadFuture.set(null); 116 assertThat(future.isDone()).isTrue(); 117 } 118 119 @Test startDownloading_delegatesCorrectly_pir()120 public void startDownloading_delegatesCorrectly_pir() throws Exception { 121 DownloadRequest downloadRequest = 122 DownloadRequest.newBuilder() 123 .setUrlToDownload("pir://example.com:1234/database/version/3") 124 .setFileUri(Uri.parse("file://dev/null")) 125 .setDownloadConstraints(DownloadConstraints.NONE) 126 .build(); 127 ListenableFuture<Void> future = downloader.startDownloading(downloadRequest); 128 129 verify(mockPirDownloader).startDownloading(downloadRequest); 130 verifyNoMoreInteractions(mockStandardDownloader); 131 verifyNoMoreInteractions(mockPirDownloader); 132 assertThat(future.isDone()).isFalse(); 133 134 // Make sure we actually got (a view of) the correct future. 135 mockPirDownloaderDownloadFuture.set(null); 136 assertThat(future.isDone()).isTrue(); 137 } 138 139 @Test isContentChanged_delegatesCorrectly_http()140 public void isContentChanged_delegatesCorrectly_http() throws Exception { 141 CheckContentChangeRequest checkContentChangeRequest = 142 CheckContentChangeRequest.newBuilder().setUrl("http://www.google.com").build(); 143 ListenableFuture<CheckContentChangeResponse> future = 144 downloader.isContentChanged(checkContentChangeRequest); 145 146 verify(mockStandardDownloader).isContentChanged(checkContentChangeRequest); 147 verifyNoMoreInteractions(mockStandardDownloader); 148 verifyNoMoreInteractions(mockPirDownloader); 149 assertThat(future.isDone()).isFalse(); 150 151 // Make sure we actually got (a view of) the correct future. 152 mockStandardDownloaderIsContentChangedFuture.set( 153 CheckContentChangeResponse.newBuilder().setContentChanged(true).build()); 154 assertThat(future.isDone()).isTrue(); 155 } 156 157 @Test isContentChanged_delegatesCorrectly_pir()158 public void isContentChanged_delegatesCorrectly_pir() throws Exception { 159 CheckContentChangeRequest checkContentChangeRequest = 160 CheckContentChangeRequest.newBuilder() 161 .setUrl("pir://example.com:1234/database/version/3") 162 .build(); 163 ListenableFuture<CheckContentChangeResponse> future = 164 downloader.isContentChanged(checkContentChangeRequest); 165 166 verify(mockPirDownloader).isContentChanged(checkContentChangeRequest); 167 verifyNoMoreInteractions(mockStandardDownloader); 168 verifyNoMoreInteractions(mockPirDownloader); 169 assertThat(future.isDone()).isFalse(); 170 171 // Make sure we actually got (a view of) the correct future. 172 mockPirDownloaderIsContentChangedFuture.set( 173 CheckContentChangeResponse.newBuilder().setContentChanged(true).build()); 174 assertThat(future.isDone()).isTrue(); 175 } 176 } 177