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