PerformInitializeTaskTest.java revision 79155590e67a30f520677d9d22e215365d595a73
1/* 2 * Copyright (C) 2017 The Android Open Source Project 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 17package com.android.server.backup.internal; 18 19import static android.app.backup.BackupTransport.TRANSPORT_ERROR; 20import static android.app.backup.BackupTransport.TRANSPORT_OK; 21 22import static com.google.common.truth.Truth.assertThat; 23 24import static org.mockito.ArgumentMatchers.any; 25import static org.mockito.ArgumentMatchers.anyInt; 26import static org.mockito.ArgumentMatchers.anyLong; 27import static org.mockito.ArgumentMatchers.eq; 28import static org.mockito.Mockito.mock; 29import static org.mockito.Mockito.never; 30import static org.mockito.Mockito.verify; 31import static org.mockito.Mockito.when; 32 33import android.annotation.Nullable; 34import android.app.AlarmManager; 35import android.app.Application; 36import android.app.PendingIntent; 37import android.app.backup.IBackupObserver; 38import android.os.DeadObjectException; 39import android.platform.test.annotations.Presubmit; 40 41import com.android.internal.backup.IBackupTransport; 42import com.android.server.backup.RefactoredBackupManagerService; 43import com.android.server.backup.TransportManager; 44import com.android.server.backup.transport.TransportClient; 45import com.android.server.backup.transport.TransportNotAvailableException; 46import com.android.server.testing.FrameworkRobolectricTestRunner; 47import com.android.server.testing.SystemLoaderClasses; 48 49import org.junit.Before; 50import org.junit.Test; 51import org.junit.runner.RunWith; 52import org.mockito.Mock; 53import org.mockito.MockitoAnnotations; 54import org.robolectric.RuntimeEnvironment; 55import org.robolectric.annotation.Config; 56 57import java.io.File; 58import java.util.Arrays; 59import java.util.List; 60 61@RunWith(FrameworkRobolectricTestRunner.class) 62@Config(manifest = Config.NONE, sdk = 26) 63@SystemLoaderClasses({PerformInitializeTaskTest.class, TransportManager.class}) 64@Presubmit 65public class PerformInitializeTaskTest { 66 private static final String[] TRANSPORT_NAMES = { 67 "android/com.android.internal.backup.LocalTransport", 68 "com.google.android.gms/.backup.migrate.service.D2dTransport", 69 "com.google.android.gms/.backup.BackupTransportService" 70 }; 71 72 private static final String TRANSPORT_NAME = TRANSPORT_NAMES[0]; 73 74 @Mock private RefactoredBackupManagerService mBackupManagerService; 75 @Mock private TransportManager mTransportManager; 76 @Mock private OnTaskFinishedListener mListener; 77 @Mock private IBackupTransport mTransport; 78 @Mock private IBackupObserver mObserver; 79 @Mock private AlarmManager mAlarmManager; 80 @Mock private PendingIntent mRunInitIntent; 81 private File mBaseStateDir; 82 83 @Before 84 public void setUp() throws Exception { 85 MockitoAnnotations.initMocks(this); 86 87 Application context = RuntimeEnvironment.application; 88 mBaseStateDir = new File(context.getCacheDir(), "base_state_dir"); 89 assertThat(mBaseStateDir.mkdir()).isTrue(); 90 91 when(mBackupManagerService.getAlarmManager()).thenReturn(mAlarmManager); 92 when(mBackupManagerService.getRunInitIntent()).thenReturn(mRunInitIntent); 93 } 94 95 @Test 96 public void testRun_callsTransportCorrectly() throws Exception { 97 setUpTransport(TRANSPORT_NAME); 98 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_OK); 99 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 100 101 performInitializeTask.run(); 102 103 verify(mTransport).initializeDevice(); 104 verify(mTransport).finishBackup(); 105 } 106 107 @Test 108 public void testRun_callsBackupManagerCorrectly() throws Exception { 109 setUpTransport(TRANSPORT_NAME); 110 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_OK); 111 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 112 113 performInitializeTask.run(); 114 115 verify(mBackupManagerService) 116 .recordInitPending(false, TRANSPORT_NAME, dirName(TRANSPORT_NAME)); 117 verify(mBackupManagerService) 118 .resetBackupState(eq(new File(mBaseStateDir, dirName(TRANSPORT_NAME)))); 119 } 120 121 @Test 122 public void testRun_callsObserverAndListenerCorrectly() throws Exception { 123 setUpTransport(TRANSPORT_NAME); 124 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_OK); 125 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 126 127 performInitializeTask.run(); 128 129 verify(mObserver).onResult(eq(TRANSPORT_NAME), eq(TRANSPORT_OK)); 130 verify(mObserver).backupFinished(eq(TRANSPORT_OK)); 131 verify(mListener).onFinished(any()); 132 } 133 134 @Test 135 public void testRun_whenInitializeDeviceFails() throws Exception { 136 setUpTransport(TRANSPORT_NAME); 137 configureTransport(mTransport, TRANSPORT_ERROR, 0); 138 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 139 140 performInitializeTask.run(); 141 142 verify(mTransport).initializeDevice(); 143 verify(mTransport, never()).finishBackup(); 144 verify(mBackupManagerService) 145 .recordInitPending(true, TRANSPORT_NAME, dirName(TRANSPORT_NAME)); 146 } 147 148 @Test 149 public void testRun_whenInitializeDeviceFails_callsObserverAndListenerCorrectly() 150 throws Exception { 151 setUpTransport(TRANSPORT_NAME); 152 configureTransport(mTransport, TRANSPORT_ERROR, 0); 153 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 154 155 performInitializeTask.run(); 156 157 verify(mObserver).onResult(eq(TRANSPORT_NAME), eq(TRANSPORT_ERROR)); 158 verify(mObserver).backupFinished(eq(TRANSPORT_ERROR)); 159 verify(mListener).onFinished(any()); 160 } 161 162 @Test 163 public void testRun_whenInitializeDeviceFails_schedulesAlarm() throws Exception { 164 setUpTransport(TRANSPORT_NAME); 165 configureTransport(mTransport, TRANSPORT_ERROR, 0); 166 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 167 168 performInitializeTask.run(); 169 170 verify(mAlarmManager).set(anyInt(), anyLong(), eq(mRunInitIntent)); 171 } 172 173 @Test 174 public void testRun_whenFinishBackupFails() throws Exception { 175 setUpTransport(TRANSPORT_NAME); 176 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_ERROR); 177 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 178 179 performInitializeTask.run(); 180 181 verify(mTransport).initializeDevice(); 182 verify(mTransport).finishBackup(); 183 verify(mBackupManagerService) 184 .recordInitPending(true, TRANSPORT_NAME, dirName(TRANSPORT_NAME)); 185 } 186 187 @Test 188 public void testRun_whenFinishBackupFails_callsObserverAndListenerCorrectly() throws Exception { 189 setUpTransport(TRANSPORT_NAME); 190 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_ERROR); 191 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 192 193 performInitializeTask.run(); 194 195 verify(mObserver).onResult(eq(TRANSPORT_NAME), eq(TRANSPORT_ERROR)); 196 verify(mObserver).backupFinished(eq(TRANSPORT_ERROR)); 197 verify(mListener).onFinished(any()); 198 } 199 200 @Test 201 public void testRun_whenFinishBackupFails_schedulesAlarm() throws Exception { 202 setUpTransport(TRANSPORT_NAME); 203 configureTransport(mTransport, TRANSPORT_OK, TRANSPORT_ERROR); 204 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 205 206 performInitializeTask.run(); 207 208 verify(mAlarmManager).set(anyInt(), anyLong(), eq(mRunInitIntent)); 209 } 210 211 @Test 212 public void testRun_whenOnlyOneTransportFails() throws Exception { 213 List<TransportData> transports = setUpTransports(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]); 214 configureTransport(transports.get(0).transportMock, TRANSPORT_ERROR, 0); 215 configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK); 216 PerformInitializeTask performInitializeTask = 217 createPerformInitializeTask(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]); 218 219 performInitializeTask.run(); 220 221 verify(transports.get(1).transportMock).initializeDevice(); 222 verify(mObserver).onResult(eq(TRANSPORT_NAMES[0]), eq(TRANSPORT_ERROR)); 223 verify(mObserver).onResult(eq(TRANSPORT_NAMES[1]), eq(TRANSPORT_OK)); 224 verify(mObserver).backupFinished(eq(TRANSPORT_ERROR)); 225 } 226 227 @Test 228 public void testRun_withMultipleTransports() throws Exception { 229 List<TransportData> transports = setUpTransports(TRANSPORT_NAMES); 230 configureTransport(transports.get(0).transportMock, TRANSPORT_OK, TRANSPORT_OK); 231 configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK); 232 configureTransport(transports.get(2).transportMock, TRANSPORT_OK, TRANSPORT_OK); 233 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAMES); 234 235 performInitializeTask.run(); 236 237 for (TransportData transport : transports) { 238 verify(mTransportManager).getTransportClient(eq(transport.transportName), any()); 239 verify(mTransportManager) 240 .disposeOfTransportClient(eq(transport.transportClientMock), any()); 241 } 242 } 243 244 @Test 245 public void testRun_whenOnlyOneTransportFails_disposesAllTransports() throws Exception { 246 List<TransportData> transports = setUpTransports(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]); 247 configureTransport(transports.get(0).transportMock, TRANSPORT_ERROR, 0); 248 configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK); 249 PerformInitializeTask performInitializeTask = 250 createPerformInitializeTask(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]); 251 252 performInitializeTask.run(); 253 254 verify(mTransportManager) 255 .disposeOfTransportClient(eq(transports.get(0).transportClientMock), any()); 256 verify(mTransportManager) 257 .disposeOfTransportClient(eq(transports.get(1).transportClientMock), any()); 258 } 259 260 @Test 261 public void testRun_whenTransportNotRegistered() throws Exception { 262 setUpTransport(new TransportData(TRANSPORT_NAME, null, null)); 263 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 264 265 performInitializeTask.run(); 266 267 verify(mTransportManager, never()).disposeOfTransportClient(any(), any()); 268 verify(mObserver, never()).onResult(any(), anyInt()); 269 verify(mObserver).backupFinished(eq(TRANSPORT_OK)); 270 } 271 272 @Test 273 public void testRun_whenOnlyOneTransportNotRegistered() throws Exception { 274 List<TransportData> transports = 275 setUpTransports( 276 new TransportData(TRANSPORT_NAMES[0], null, null), 277 new TransportData(TRANSPORT_NAMES[1])); 278 String registeredTransportName = transports.get(1).transportName; 279 IBackupTransport registeredTransport = transports.get(1).transportMock; 280 TransportClient registeredTransportClient = transports.get(1).transportClientMock; 281 PerformInitializeTask performInitializeTask = 282 createPerformInitializeTask(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]); 283 284 performInitializeTask.run(); 285 286 verify(registeredTransport).initializeDevice(); 287 verify(mTransportManager).disposeOfTransportClient(eq(registeredTransportClient), any()); 288 verify(mObserver).onResult(eq(registeredTransportName), eq(TRANSPORT_OK)); 289 } 290 291 @Test 292 public void testRun_whenTransportNotAvailable() throws Exception { 293 TransportClient transportClient = mock(TransportClient.class); 294 setUpTransport(new TransportData(TRANSPORT_NAME, null, transportClient)); 295 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 296 297 performInitializeTask.run(); 298 299 verify(mTransportManager).disposeOfTransportClient(eq(transportClient), any()); 300 verify(mObserver).backupFinished(eq(TRANSPORT_ERROR)); 301 verify(mListener).onFinished(any()); 302 } 303 304 @Test 305 public void testRun_whenTransportThrowsDeadObjectException() throws Exception { 306 TransportClient transportClient = mock(TransportClient.class); 307 setUpTransport(new TransportData(TRANSPORT_NAME, mTransport, transportClient)); 308 when(mTransport.initializeDevice()).thenThrow(DeadObjectException.class); 309 PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME); 310 311 performInitializeTask.run(); 312 313 verify(mTransportManager).disposeOfTransportClient(eq(transportClient), any()); 314 verify(mObserver).backupFinished(eq(TRANSPORT_ERROR)); 315 verify(mListener).onFinished(any()); 316 } 317 318 private PerformInitializeTask createPerformInitializeTask(String... transportNames) { 319 return new PerformInitializeTask( 320 mBackupManagerService, 321 mTransportManager, 322 transportNames, 323 mObserver, 324 mListener, 325 mBaseStateDir); 326 } 327 328 private void configureTransport( 329 IBackupTransport transportMock, int initializeDeviceStatus, int finishBackupStatus) 330 throws Exception { 331 when(transportMock.initializeDevice()).thenReturn(initializeDeviceStatus); 332 when(transportMock.finishBackup()).thenReturn(finishBackupStatus); 333 } 334 335 private List<TransportData> setUpTransports(String... transportNames) throws Exception { 336 return setUpTransports( 337 Arrays.stream(transportNames) 338 .map(TransportData::new) 339 .toArray(TransportData[]::new)); 340 } 341 342 /** @see #setUpTransport(TransportData) */ 343 private List<TransportData> setUpTransports(TransportData... transports) throws Exception { 344 for (TransportData transport : transports) { 345 setUpTransport(transport); 346 } 347 return Arrays.asList(transports); 348 } 349 350 private void setUpTransport(String transportName) throws Exception { 351 setUpTransport(new TransportData(transportName, mTransport, mock(TransportClient.class))); 352 } 353 354 /** 355 * Configures transport according to {@link TransportData}: 356 * 357 * <ul> 358 * <li>{@link TransportData#transportMock} {@code null} means {@link 359 * TransportClient#connectOrThrow(String)} throws {@link TransportNotAvailableException}. 360 * <li>{@link TransportData#transportClientMock} {@code null} means {@link 361 * TransportManager#getTransportClient(String, String)} returns {@code null}. 362 * </ul> 363 */ 364 private void setUpTransport(TransportData transport) throws Exception { 365 String transportName = transport.transportName; 366 String transportDirName = dirName(transportName); 367 IBackupTransport transportMock = transport.transportMock; 368 TransportClient transportClientMock = transport.transportClientMock; 369 370 if (transportMock != null) { 371 when(transportMock.name()).thenReturn(transportName); 372 when(transportMock.transportDirName()).thenReturn(transportDirName); 373 } 374 375 if (transportClientMock != null) { 376 when(transportClientMock.getTransportDirName()).thenReturn(transportDirName); 377 if (transportMock != null) { 378 when(transportClientMock.connectOrThrow(any())).thenReturn(transportMock); 379 } else { 380 when(transportClientMock.connectOrThrow(any())) 381 .thenThrow(TransportNotAvailableException.class); 382 } 383 } 384 385 when(mTransportManager.getTransportClient(eq(transportName), any())) 386 .thenReturn(transportClientMock); 387 } 388 389 private String dirName(String transportName) { 390 return transportName + "_dir_name"; 391 } 392 393 private static class TransportData { 394 private final String transportName; 395 @Nullable private final IBackupTransport transportMock; 396 @Nullable private final TransportClient transportClientMock; 397 398 private TransportData( 399 String transportName, 400 @Nullable IBackupTransport transportMock, 401 @Nullable TransportClient transportClientMock) { 402 this.transportName = transportName; 403 this.transportMock = transportMock; 404 this.transportClientMock = transportClientMock; 405 } 406 407 private TransportData(String transportName) { 408 this(transportName, mock(IBackupTransport.class), mock(TransportClient.class)); 409 } 410 } 411} 412