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.file.backends; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.junit.Assert.assertThrows; 20 import static org.mockito.Mockito.mock; 21 import static org.mockito.Mockito.when; 22 23 import android.accounts.Account; 24 import android.net.Uri; 25 import androidx.test.core.app.ApplicationProvider; 26 import com.google.android.libraries.mobiledatadownload.file.common.MalformedUriException; 27 import com.google.common.util.concurrent.Futures; 28 import com.google.thirdparty.robolectric.GoogleRobolectricTestRunner; 29 import java.io.File; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 33 /** Test {@link com.google.android.libraries.mobiledatadownload.file.backends.AndroidUriAdapter}. */ 34 @RunWith(GoogleRobolectricTestRunner.class) 35 public final class AndroidUriAdapterTest { 36 37 private AndroidUriAdapter adapter = 38 AndroidUriAdapter.forContext(ApplicationProvider.getApplicationContext()); 39 40 @Test shouldGenerateFileFromUri()41 public void shouldGenerateFileFromUri() throws Exception { 42 File file = adapter.toFile(Uri.parse("android://package/files/common/shared/path")); 43 assertThat(file.getPath()).endsWith("/files/common/shared/path"); 44 } 45 46 @Test shouldGenerateCacheFromUri()47 public void shouldGenerateCacheFromUri() throws Exception { 48 File file = adapter.toFile(Uri.parse("android://package/cache/common/shared/path")); 49 assertThat(file.getPath()).endsWith("/cache/common/shared/path"); 50 } 51 52 @Test shouldGenerateFileFromExternalLocationUri()53 public void shouldGenerateFileFromExternalLocationUri() throws Exception { 54 File file = adapter.toFile(Uri.parse("android://package/external/common/shared/path")); 55 assertThat(file.getPath()).endsWith("/external-files/common/shared/path"); 56 } 57 58 @Test managedLocation_withSharedAccount_doesNotRequireAccountManager()59 public void managedLocation_withSharedAccount_doesNotRequireAccountManager() throws Exception { 60 File file = adapter.toFile(Uri.parse("android://package/managed/common/shared/path")); 61 assertThat(file.getPath()).endsWith("/files/managed/common/shared/path"); 62 } 63 64 @Test managedLocation_withAccount_requiresAccountManager()65 public void managedLocation_withAccount_requiresAccountManager() throws Exception { 66 assertThrows( 67 MalformedUriException.class, 68 () -> 69 adapter.toFile( 70 Uri.parse("android://package/managed/common/google.com%3Ayou%40gmail.com/path"))); 71 } 72 73 @Test managedLocation_validatesAccount()74 public void managedLocation_validatesAccount() throws Exception { 75 AccountManager mockManager = mock(AccountManager.class); 76 adapter = 77 AndroidUriAdapter.forContext(ApplicationProvider.getApplicationContext(), mockManager); 78 79 assertThrows( 80 MalformedUriException.class, 81 () -> adapter.toFile(Uri.parse("android://package/managed/common/invalid-account/path"))); 82 } 83 84 @Test managedLocation_doesNotRequireAccountSegment()85 public void managedLocation_doesNotRequireAccountSegment() throws Exception { 86 AccountManager mockManager = mock(AccountManager.class); 87 adapter = 88 AndroidUriAdapter.forContext(ApplicationProvider.getApplicationContext(), mockManager); 89 90 File file = adapter.toFile(Uri.parse("android://package/managed/common/")); 91 assertThat(file.getPath()).endsWith("/files/managed/common"); 92 } 93 94 @Test managedLocation_obfuscatesAccountSegment()95 public void managedLocation_obfuscatesAccountSegment() throws Exception { 96 Account account = new Account("<internal>@gmail.com", "google.com"); 97 AccountManager mockManager = mock(AccountManager.class); 98 when(mockManager.getAccountId(account)).thenReturn(Futures.immediateFuture(123)); 99 100 adapter = 101 AndroidUriAdapter.forContext(ApplicationProvider.getApplicationContext(), mockManager); 102 103 File file = 104 adapter.toFile( 105 Uri.parse("android://package/managed/common/google.com%3Ayou%40gmail.com/path")); 106 assertThat(file.getPath()).endsWith("/files/managed/common/123/path"); 107 } 108 109 @Test ignoresFragmentAtCallersPeril()110 public void ignoresFragmentAtCallersPeril() throws Exception { 111 File file = adapter.toFile(Uri.parse("android://package/files/common/shared/path#fragment")); 112 assertThat(file.getPath()).endsWith("/files/common/shared/path"); 113 } 114 115 @Test requiresAndroidScheme()116 public void requiresAndroidScheme() throws Exception { 117 assertThrows( 118 MalformedUriException.class, 119 () -> 120 AndroidUriAdapter.validate(Uri.parse("notandroid://package/files/common/shared/path"))); 121 assertThrows( 122 MalformedUriException.class, 123 () -> adapter.toFile(Uri.parse("notandroid://package/files/common/shared/path"))); 124 } 125 126 @Test requiresPath()127 public void requiresPath() throws Exception { 128 assertThrows( 129 MalformedUriException.class, () -> AndroidUriAdapter.validate(Uri.parse("android:///"))); 130 assertThrows(MalformedUriException.class, () -> adapter.toFile(Uri.parse("android://package"))); 131 assertThrows( 132 MalformedUriException.class, () -> adapter.toFile(Uri.parse("android://package/"))); 133 } 134 135 @Test requiresValidLogicalLocation()136 public void requiresValidLogicalLocation() throws Exception { 137 assertThrows( 138 MalformedUriException.class, 139 () -> adapter.toFile(Uri.parse("android://package/invalid/common/shared/path"))); 140 } 141 142 @Test requiresEmptyQuery()143 public void requiresEmptyQuery() throws Exception { 144 assertThrows( 145 MalformedUriException.class, 146 () -> 147 AndroidUriAdapter.validate( 148 Uri.parse("android://package/files/common/shared/path?query"))); 149 assertThrows( 150 MalformedUriException.class, 151 () -> adapter.toFile(Uri.parse("android://package/files/common/shared/path?query"))); 152 } 153 154 @Test shouldDecodePath()155 public void shouldDecodePath() throws Exception { 156 Uri uri = 157 Uri.parse( 158 "android://org.robolectric.default/files/common/google.com%3Ayou%40gmail.com/path"); 159 File file = adapter.toFile(uri); 160 assertThat(file.getPath()).endsWith("/files/common/google.com:<internal>@gmail.com/path"); 161 } 162 } 163