1 /* 2 * Copyright (C) 2020 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 17 package android.app.backup; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.when; 22 23 import android.app.IBackupAgent; 24 import android.app.backup.BackupAgent.IncludeExcludeRules; 25 import android.app.backup.BackupAnnotations.BackupDestination; 26 import android.app.backup.BackupAnnotations.OperationType; 27 import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; 28 import android.content.Context; 29 import android.os.ParcelFileDescriptor; 30 import android.os.UserHandle; 31 import android.platform.test.annotations.Presubmit; 32 import android.platform.test.flag.junit.SetFlagsRule; 33 import android.util.ArraySet; 34 35 import androidx.test.runner.AndroidJUnit4; 36 37 import com.android.server.backup.Flags; 38 39 import org.junit.Before; 40 import org.junit.Rule; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.Mock; 44 import org.mockito.MockitoAnnotations; 45 46 import java.io.FileInputStream; 47 import java.io.FileOutputStream; 48 import java.io.IOException; 49 import java.nio.charset.StandardCharsets; 50 import java.util.Collections; 51 import java.util.Map; 52 import java.util.Set; 53 54 @Presubmit 55 @RunWith(AndroidJUnit4.class) 56 public class BackupAgentTest { 57 // An arbitrary user. 58 private static final UserHandle USER_HANDLE = new UserHandle(15); 59 private static final String DATA_TYPE_BACKED_UP = "test data type"; 60 61 @Mock IBackupManager mIBackupManager; 62 @Mock FullBackup.BackupScheme mBackupScheme; 63 @Mock Context mContext; 64 65 @Rule 66 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 67 68 @Before setUp()69 public void setUp() { 70 MockitoAnnotations.initMocks(this); 71 } 72 73 @Test testGetIncludeExcludeRules_isNotMigration_returnsRules()74 public void testGetIncludeExcludeRules_isNotMigration_returnsRules() throws Exception { 75 PathWithRequiredFlags path = new PathWithRequiredFlags("path", /* requiredFlags */ 0); 76 Map<String, Set<PathWithRequiredFlags>> includePaths = Collections.singletonMap("test", 77 Collections.singleton(path)); 78 ArraySet<PathWithRequiredFlags> excludePaths = new ArraySet<>(); 79 excludePaths.add(path); 80 IncludeExcludeRules expectedRules = new IncludeExcludeRules(includePaths, excludePaths); 81 82 BackupAgent backupAgent = getAgentForBackupDestination(BackupDestination.CLOUD); 83 when(mBackupScheme.maybeParseAndGetCanonicalExcludePaths()).thenReturn(excludePaths); 84 when(mBackupScheme.maybeParseAndGetCanonicalIncludePaths()).thenReturn(includePaths); 85 86 IncludeExcludeRules rules = backupAgent.getIncludeExcludeRules(mBackupScheme); 87 assertThat(rules).isEqualTo(expectedRules); 88 } 89 90 @Test getBackupRestoreEventLogger_beforeOnCreate_isNull()91 public void getBackupRestoreEventLogger_beforeOnCreate_isNull() { 92 BackupAgent agent = new TestFullBackupAgent(); 93 94 assertThat(agent.getBackupRestoreEventLogger()).isNull(); 95 } 96 97 @Test getBackupRestoreEventLogger_afterOnCreateForBackup_initializedForBackup()98 public void getBackupRestoreEventLogger_afterOnCreateForBackup_initializedForBackup() { 99 BackupAgent agent = new TestFullBackupAgent(); 100 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.BACKUP); 101 102 assertThat(agent.getBackupRestoreEventLogger().getOperationType()).isEqualTo( 103 OperationType.BACKUP); 104 } 105 106 @Test getBackupRestoreEventLogger_afterOnCreateForRestore_initializedForRestore()107 public void getBackupRestoreEventLogger_afterOnCreateForRestore_initializedForRestore() { 108 BackupAgent agent = new TestFullBackupAgent(); 109 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.RESTORE); 110 111 assertThat(agent.getBackupRestoreEventLogger().getOperationType()).isEqualTo( 112 OperationType.RESTORE); 113 } 114 115 @Test getBackupRestoreEventLogger_afterBackup_containsLogsLoggedByAgent()116 public void getBackupRestoreEventLogger_afterBackup_containsLogsLoggedByAgent() 117 throws Exception { 118 BackupAgent agent = new TestFullBackupAgent(); 119 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.BACKUP); 120 121 // TestFullBackupAgent logs DATA_TYPE_BACKED_UP when onFullBackup is called. 122 agent.onFullBackup(new FullBackupDataOutput(/* quota = */ 0)); 123 124 assertThat(agent.getBackupRestoreEventLogger().getLoggingResults().get(0).getDataType()) 125 .isEqualTo(DATA_TYPE_BACKED_UP); 126 } 127 128 @Test testClearLogger_clearsPendingLogs()129 public void testClearLogger_clearsPendingLogs() throws Exception { 130 BackupAgent agent = new TestFullBackupAgent(); 131 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.BACKUP); 132 133 agent.onFullBackup(new FullBackupDataOutput(/* quota = */ 0)); 134 agent.clearBackupRestoreEventLogger(); 135 136 assertThat(agent.getBackupRestoreEventLogger().getLoggingResults().size()).isEqualTo(0); 137 } 138 139 @Test testClearLoggerBetweenBackups_restartsSuccessCount()140 public void testClearLoggerBetweenBackups_restartsSuccessCount() throws Exception { 141 BackupAgent agent = new TestFullBackupAgent(); 142 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.BACKUP); 143 144 agent.onFullBackup(new FullBackupDataOutput(/* quota = */ 0)); 145 agent.clearBackupRestoreEventLogger(); 146 agent.onFullBackup(new FullBackupDataOutput(/* quota = */ 0)); 147 148 assertThat(agent.getBackupRestoreEventLogger().getLoggingResults().get( 149 0).getSuccessCount()).isEqualTo(1); 150 } 151 152 @Test doRestoreFile_agentOverrideIgnoresFile_consumesAllBytesInBuffer()153 public void doRestoreFile_agentOverrideIgnoresFile_consumesAllBytesInBuffer() throws Exception { 154 mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_CLEAR_PIPE_AFTER_RESTORE_FILE); 155 BackupAgent agent = new TestRestoreIgnoringFullBackupAgent(); 156 agent.attach(mContext); 157 agent.onCreate(USER_HANDLE, BackupDestination.CLOUD, OperationType.RESTORE); 158 IBackupAgent agentBinder = (IBackupAgent) agent.onBind(); 159 160 ParcelFileDescriptor[] pipes = ParcelFileDescriptor.createPipe(); 161 FileOutputStream writeSide = new FileOutputStream( 162 pipes[1].getFileDescriptor()); 163 writeSide.write("Hello".getBytes(StandardCharsets.UTF_8)); 164 165 agentBinder.doRestoreFile(pipes[0], /* length= */ 5, BackupAgent.TYPE_FILE, 166 FullBackup.FILES_TREE_TOKEN, /* path= */ "hello_file", /* mode= */ 167 0666, /* mtime= */ 12345, /* token= */ 6789, mIBackupManager); 168 169 try (FileInputStream in = new FileInputStream(pipes[0].getFileDescriptor())) { 170 assertThat(in.available()).isEqualTo(0); 171 } finally { 172 pipes[0].close(); 173 pipes[1].close(); 174 } 175 } 176 getAgentForBackupDestination(@ackupDestination int backupDestination)177 private BackupAgent getAgentForBackupDestination(@BackupDestination int backupDestination) { 178 BackupAgent agent = new TestFullBackupAgent(); 179 agent.onCreate(USER_HANDLE, backupDestination); 180 return agent; 181 } 182 183 private static class TestFullBackupAgent extends BackupAgent { 184 @Override onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)185 public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 186 ParcelFileDescriptor newState) throws IOException { 187 // Left empty as this is a full backup agent. 188 } 189 190 @Override onFullBackup(FullBackupDataOutput data)191 public void onFullBackup(FullBackupDataOutput data) { 192 getBackupRestoreEventLogger().logItemsBackedUp(DATA_TYPE_BACKED_UP, 1); 193 } 194 195 @Override onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)196 public void onRestore(BackupDataInput data, int appVersionCode, 197 ParcelFileDescriptor newState) throws IOException { 198 // Left empty as this is a full backup agent. 199 } 200 } 201 202 private static class TestRestoreIgnoringFullBackupAgent extends TestFullBackupAgent { 203 204 @Override onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime)205 protected void onRestoreFile(ParcelFileDescriptor data, long size, 206 int type, String domain, String path, long mode, long mtime) 207 throws IOException { 208 // Ignore the file and don't consume any data. 209 } 210 } 211 } 212