• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 android.app.backup.BackupAnnotations.OperationType.BACKUP;
20 import static android.app.backup.BackupAnnotations.OperationType.RESTORE;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static junit.framework.Assert.fail;
25 
26 import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
27 import android.os.Parcel;
28 import android.platform.test.annotations.Presubmit;
29 import android.platform.test.flag.junit.SetFlagsRule;
30 
31 import androidx.test.runner.AndroidJUnit4;
32 
33 import com.android.server.backup.Flags;
34 
35 import org.junit.Before;
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.nio.charset.StandardCharsets;
41 import java.security.MessageDigest;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.List;
45 import java.util.Optional;
46 
47 @Presubmit
48 @RunWith(AndroidJUnit4.class)
49 public class BackupRestoreEventLoggerTest {
50     private static final int DATA_TYPES_ALLOWED_AFTER_FLAG = 150;
51 
52     private static final int DATA_TYPES_ALLOWED_BEFORE_FLAG = 15;
53 
54     private static final String DATA_TYPE_1 = "data_type_1";
55     private static final String DATA_TYPE_2 = "data_type_2";
56     private static final String ERROR_1 = "error_1";
57     private static final String ERROR_2 = "error_2";
58     private static final String METADATA_1 = "metadata_1";
59     private static final String METADATA_2 = "metadata_2";
60 
61     private BackupRestoreEventLogger mLogger;
62     private MessageDigest mHashDigest;
63 
64     @Rule
65     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
66 
67     @Before
setUp()68     public void setUp() throws Exception {
69         mHashDigest = MessageDigest.getInstance("SHA-256");
70     }
71 
72     @Test
testBackupLogger_rejectsRestoreLogs()73     public void testBackupLogger_rejectsRestoreLogs() {
74         mLogger = new BackupRestoreEventLogger(BACKUP);
75 
76         mLogger.logItemsRestored(DATA_TYPE_1, /* count */ 5);
77         mLogger.logItemsRestoreFailed(DATA_TYPE_1, /* count */ 5, ERROR_1);
78         mLogger.logRestoreMetadata(DATA_TYPE_1, /* metadata */ "metadata");
79 
80         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_1)).isEqualTo(Optional.empty());
81     }
82 
83     @Test
testRestoreLogger_rejectsBackupLogs()84     public void testRestoreLogger_rejectsBackupLogs() {
85         mLogger = new BackupRestoreEventLogger(RESTORE);
86 
87         mLogger.logItemsBackedUp(DATA_TYPE_1, /* count */ 5);
88         mLogger.logItemsBackupFailed(DATA_TYPE_1, /* count */ 5, ERROR_1);
89         mLogger.logBackupMetadata(DATA_TYPE_1, /* metadata */ "metadata");
90 
91         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_1)).isEqualTo(Optional.empty());
92     }
93 
94     @Test
testBackupLogger_datatypeLimitFlagOff_onlyAcceptsAllowedNumberOfDataTypes()95     public void testBackupLogger_datatypeLimitFlagOff_onlyAcceptsAllowedNumberOfDataTypes() {
96         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_INCREASE_DATATYPES_FOR_AGENT_LOGGING);
97         mLogger = new BackupRestoreEventLogger(BACKUP);
98 
99         for (int i = 0; i < DATA_TYPES_ALLOWED_BEFORE_FLAG; i++) {
100             String dataType = DATA_TYPE_1 + i;
101             mLogger.logItemsBackedUp(dataType, /* count */ 5);
102             mLogger.logItemsBackupFailed(dataType, /* count */ 5, /* error */ null);
103             mLogger.logBackupMetadata(dataType, METADATA_1);
104 
105             assertThat(getResultForDataTypeIfPresent(mLogger, dataType)).isNotEqualTo(
106                     Optional.empty());
107         }
108 
109         mLogger.logItemsBackedUp(DATA_TYPE_2, /* count */ 5);
110         mLogger.logItemsBackupFailed(DATA_TYPE_2, /* count */ 5, /* error */ null);
111         mLogger.logRestoreMetadata(DATA_TYPE_2, METADATA_1);
112         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_2)).isEqualTo(Optional.empty());
113     }
114 
115     @Test
testRestoreLogger_datatypeLimitFlagOff_onlyAcceptsAllowedNumberOfDataTypes()116     public void testRestoreLogger_datatypeLimitFlagOff_onlyAcceptsAllowedNumberOfDataTypes() {
117         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_INCREASE_DATATYPES_FOR_AGENT_LOGGING);
118         mLogger = new BackupRestoreEventLogger(RESTORE);
119 
120         for (int i = 0; i < DATA_TYPES_ALLOWED_BEFORE_FLAG; i++) {
121             String dataType = DATA_TYPE_1 + i;
122             mLogger.logItemsRestored(dataType, /* count */ 5);
123             mLogger.logItemsRestoreFailed(dataType, /* count */ 5, /* error */ null);
124             mLogger.logRestoreMetadata(dataType, METADATA_1);
125 
126             assertThat(getResultForDataTypeIfPresent(mLogger, dataType)).isNotEqualTo(
127                     Optional.empty());
128         }
129 
130         mLogger.logItemsRestored(DATA_TYPE_2, /* count */ 5);
131         mLogger.logItemsRestoreFailed(DATA_TYPE_2, /* count */ 5, /* error */ null);
132         mLogger.logRestoreMetadata(DATA_TYPE_2, METADATA_1);
133         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_2)).isEqualTo(Optional.empty());
134     }
135 
136     @Test
testBackupLogger_datatypeLimitFlagOn_onlyAcceptsAllowedNumberOfDataTypes()137     public void testBackupLogger_datatypeLimitFlagOn_onlyAcceptsAllowedNumberOfDataTypes() {
138         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_INCREASE_DATATYPES_FOR_AGENT_LOGGING);
139         mLogger = new BackupRestoreEventLogger(BACKUP);
140 
141         for (int i = 0; i < DATA_TYPES_ALLOWED_AFTER_FLAG; i++) {
142             String dataType = DATA_TYPE_1 + i;
143             mLogger.logItemsBackedUp(dataType, /* count */ 5);
144             mLogger.logItemsBackupFailed(dataType, /* count */ 5, /* error */ null);
145             mLogger.logBackupMetadata(dataType, METADATA_1);
146 
147             assertThat(getResultForDataTypeIfPresent(mLogger, dataType)).isNotEqualTo(
148                     Optional.empty());
149         }
150 
151         mLogger.logItemsBackedUp(DATA_TYPE_2, /* count */ 5);
152         mLogger.logItemsBackupFailed(DATA_TYPE_2, /* count */ 5, /* error */ null);
153         mLogger.logRestoreMetadata(DATA_TYPE_2, METADATA_1);
154         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_2)).isEqualTo(Optional.empty());
155     }
156 
157     @Test
testRestoreLogger_datatypeLimitFlagOn_onlyAcceptsAllowedNumberOfDataTypes()158     public void testRestoreLogger_datatypeLimitFlagOn_onlyAcceptsAllowedNumberOfDataTypes() {
159         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_INCREASE_DATATYPES_FOR_AGENT_LOGGING);
160         mLogger = new BackupRestoreEventLogger(RESTORE);
161 
162         for (int i = 0; i < DATA_TYPES_ALLOWED_AFTER_FLAG; i++) {
163             String dataType = DATA_TYPE_1 + i;
164             mLogger.logItemsRestored(dataType, /* count */ 5);
165             mLogger.logItemsRestoreFailed(dataType, /* count */ 5, /* error */ null);
166             mLogger.logRestoreMetadata(dataType, METADATA_1);
167 
168             assertThat(getResultForDataTypeIfPresent(mLogger, dataType)).isNotEqualTo(
169                     Optional.empty());
170         }
171 
172         mLogger.logItemsRestored(DATA_TYPE_2, /* count */ 5);
173         mLogger.logItemsRestoreFailed(DATA_TYPE_2, /* count */ 5, /* error */ null);
174         mLogger.logRestoreMetadata(DATA_TYPE_2, METADATA_1);
175         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_2)).isEqualTo(Optional.empty());
176     }
177 
178     @Test
testLogBackupMetadata_repeatedCalls_recordsLatestMetadataHash()179     public void testLogBackupMetadata_repeatedCalls_recordsLatestMetadataHash() {
180         mLogger = new BackupRestoreEventLogger(BACKUP);
181 
182         mLogger.logBackupMetadata(DATA_TYPE_1, METADATA_1);
183         mLogger.logBackupMetadata(DATA_TYPE_1, METADATA_2);
184 
185         byte[] recordedHash = getResultForDataType(mLogger, DATA_TYPE_1).getMetadataHash();
186         byte[] expectedHash = getMetaDataHash(METADATA_2);
187         assertThat(Arrays.equals(recordedHash, expectedHash)).isTrue();
188     }
189 
190     @Test
testLogRestoreMetadata_repeatedCalls_recordsLatestMetadataHash()191     public void testLogRestoreMetadata_repeatedCalls_recordsLatestMetadataHash() {
192         mLogger = new BackupRestoreEventLogger(RESTORE);
193 
194         mLogger.logRestoreMetadata(DATA_TYPE_1, METADATA_1);
195         mLogger.logRestoreMetadata(DATA_TYPE_1, METADATA_2);
196 
197         byte[] recordedHash = getResultForDataType(mLogger, DATA_TYPE_1).getMetadataHash();
198         byte[] expectedHash = getMetaDataHash(METADATA_2);
199         assertThat(Arrays.equals(recordedHash, expectedHash)).isTrue();
200     }
201 
202     @Test
testLogItemsBackedUp_repeatedCalls_recordsTotalItems()203     public void testLogItemsBackedUp_repeatedCalls_recordsTotalItems() {
204         mLogger = new BackupRestoreEventLogger(BACKUP);
205 
206         int firstCount = 10;
207         int secondCount = 5;
208         mLogger.logItemsBackedUp(DATA_TYPE_1, firstCount);
209         mLogger.logItemsBackedUp(DATA_TYPE_1, secondCount);
210 
211         int dataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getSuccessCount();
212         assertThat(dataTypeCount).isEqualTo(firstCount + secondCount);
213     }
214 
215     @Test
testLogItemsRestored_repeatedCalls_recordsTotalItems()216     public void testLogItemsRestored_repeatedCalls_recordsTotalItems() {
217         mLogger = new BackupRestoreEventLogger(RESTORE);
218 
219         int firstCount = 10;
220         int secondCount = 5;
221         mLogger.logItemsRestored(DATA_TYPE_1, firstCount);
222         mLogger.logItemsRestored(DATA_TYPE_1, secondCount);
223 
224         int dataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getSuccessCount();
225         assertThat(dataTypeCount).isEqualTo(firstCount + secondCount);
226     }
227 
228     @Test
testLogItemsBackedUp_multipleDataTypes_recordsEachDataType()229     public void testLogItemsBackedUp_multipleDataTypes_recordsEachDataType() {
230         mLogger = new BackupRestoreEventLogger(BACKUP);
231 
232         int firstCount = 10;
233         int secondCount = 5;
234         mLogger.logItemsBackedUp(DATA_TYPE_1, firstCount);
235         mLogger.logItemsBackedUp(DATA_TYPE_2, secondCount);
236 
237         int firstDataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getSuccessCount();
238         int secondDataTypeCount = getResultForDataType(mLogger, DATA_TYPE_2).getSuccessCount();
239         assertThat(firstDataTypeCount).isEqualTo(firstCount);
240         assertThat(secondDataTypeCount).isEqualTo(secondCount);
241     }
242 
243     @Test
testLogItemsRestored_multipleDataTypes_recordsEachDataType()244     public void testLogItemsRestored_multipleDataTypes_recordsEachDataType() {
245         mLogger = new BackupRestoreEventLogger(RESTORE);
246 
247         int firstCount = 10;
248         int secondCount = 5;
249         mLogger.logItemsRestored(DATA_TYPE_1, firstCount);
250         mLogger.logItemsRestored(DATA_TYPE_2, secondCount);
251 
252         int firstDataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getSuccessCount();
253         int secondDataTypeCount = getResultForDataType(mLogger, DATA_TYPE_2).getSuccessCount();
254         assertThat(firstDataTypeCount).isEqualTo(firstCount);
255         assertThat(secondDataTypeCount).isEqualTo(secondCount);
256     }
257 
258     @Test
testLogItemsBackupFailed_repeatedCalls_recordsTotalItems()259     public void testLogItemsBackupFailed_repeatedCalls_recordsTotalItems() {
260         mLogger = new BackupRestoreEventLogger(BACKUP);
261 
262         int firstCount = 10;
263         int secondCount = 5;
264         mLogger.logItemsBackupFailed(DATA_TYPE_1, firstCount, /* error */ null);
265         mLogger.logItemsBackupFailed(DATA_TYPE_1, secondCount, "error");
266 
267         int dataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getFailCount();
268         assertThat(dataTypeCount).isEqualTo(firstCount + secondCount);
269     }
270 
271     @Test
testLogItemsRestoreFailed_repeatedCalls_recordsTotalItems()272     public void testLogItemsRestoreFailed_repeatedCalls_recordsTotalItems() {
273         mLogger = new BackupRestoreEventLogger(RESTORE);
274 
275         int firstCount = 10;
276         int secondCount = 5;
277         mLogger.logItemsRestoreFailed(DATA_TYPE_1, firstCount, /* error */ null);
278         mLogger.logItemsRestoreFailed(DATA_TYPE_1, secondCount, "error");
279 
280         int dataTypeCount = getResultForDataType(mLogger, DATA_TYPE_1).getFailCount();
281         assertThat(dataTypeCount).isEqualTo(firstCount + secondCount);
282     }
283 
284     @Test
testLogItemsBackupFailed_multipleErrors_recordsEachError()285     public void testLogItemsBackupFailed_multipleErrors_recordsEachError() {
286         mLogger = new BackupRestoreEventLogger(BACKUP);
287 
288         int firstCount = 10;
289         int secondCount = 5;
290         mLogger.logItemsBackupFailed(DATA_TYPE_1, firstCount, ERROR_1);
291         mLogger.logItemsBackupFailed(DATA_TYPE_1, secondCount, ERROR_2);
292 
293         int firstErrorTypeCount =
294                 getResultForDataType(mLogger, DATA_TYPE_1).getErrors().get(ERROR_1);
295         int secondErrorTypeCount =
296                 getResultForDataType(mLogger, DATA_TYPE_1).getErrors().get(ERROR_2);
297         assertThat(firstErrorTypeCount).isEqualTo(firstCount);
298         assertThat(secondErrorTypeCount).isEqualTo(secondCount);
299     }
300 
301     @Test
testLogItemsRestoreFailed_multipleErrors_recordsEachError()302     public void testLogItemsRestoreFailed_multipleErrors_recordsEachError() {
303         mLogger = new BackupRestoreEventLogger(RESTORE);
304 
305         int firstCount = 10;
306         int secondCount = 5;
307         mLogger.logItemsRestoreFailed(DATA_TYPE_1, firstCount, ERROR_1);
308         mLogger.logItemsRestoreFailed(DATA_TYPE_1, secondCount, ERROR_2);
309 
310         int firstErrorTypeCount =
311                 getResultForDataType(mLogger, DATA_TYPE_1).getErrors().get(ERROR_1);
312         int secondErrorTypeCount =
313                 getResultForDataType(mLogger, DATA_TYPE_1).getErrors().get(ERROR_2);
314         assertThat(firstErrorTypeCount).isEqualTo(firstCount);
315         assertThat(secondErrorTypeCount).isEqualTo(secondCount);
316     }
317 
318     @Test
testGetLoggingResults_resultsParceledAndUnparceled_recreatedCorrectly()319     public void testGetLoggingResults_resultsParceledAndUnparceled_recreatedCorrectly() {
320         mLogger = new BackupRestoreEventLogger(RESTORE);
321         int firstTypeSuccessCount = 1;
322         int firstTypeErrorOneCount = 2;
323         int firstTypeErrorTwoCount = 3;
324         mLogger.logItemsRestored(DATA_TYPE_1, firstTypeSuccessCount);
325         mLogger.logItemsRestoreFailed(DATA_TYPE_1, firstTypeErrorOneCount, ERROR_1);
326         mLogger.logItemsRestoreFailed(DATA_TYPE_1, firstTypeErrorTwoCount, ERROR_2);
327         mLogger.logRestoreMetadata(DATA_TYPE_1, METADATA_1);
328         int secondTypeSuccessCount = 4;
329         int secondTypeErrorOneCount = 5;
330         mLogger.logItemsRestored(DATA_TYPE_2, secondTypeSuccessCount);
331         mLogger.logItemsRestoreFailed(DATA_TYPE_2, secondTypeErrorOneCount, ERROR_1);
332 
333         List<DataTypeResult> resultsList = mLogger.getLoggingResults();
334         Parcel parcel = Parcel.obtain();
335 
336         parcel.writeParcelableList(resultsList, /* flags= */ 0);
337 
338         parcel.setDataPosition(0);
339         List<DataTypeResult> recreatedList = new ArrayList<>();
340         parcel.readParcelableList(
341                 recreatedList, DataTypeResult.class.getClassLoader(), DataTypeResult.class);
342 
343         assertThat(recreatedList.get(0).getDataType()).isEqualTo(DATA_TYPE_1);
344         assertThat(recreatedList.get(0).getSuccessCount()).isEqualTo(firstTypeSuccessCount);
345         assertThat(recreatedList.get(0).getFailCount())
346                 .isEqualTo(firstTypeErrorOneCount + firstTypeErrorTwoCount);
347         assertThat(recreatedList.get(0).getErrors().get(ERROR_1)).isEqualTo(firstTypeErrorOneCount);
348         assertThat(recreatedList.get(0).getErrors().get(ERROR_2)).isEqualTo(firstTypeErrorTwoCount);
349         assertThat(recreatedList.get(1).getDataType()).isEqualTo(DATA_TYPE_2);
350         assertThat(recreatedList.get(1).getSuccessCount()).isEqualTo(secondTypeSuccessCount);
351         assertThat(recreatedList.get(1).getFailCount()).isEqualTo(secondTypeErrorOneCount);
352         assertThat(recreatedList.get(1).getErrors().get(ERROR_1))
353                 .isEqualTo(secondTypeErrorOneCount);
354     }
355 
356     @Test
testClearData_clearsAllResults()357     public void testClearData_clearsAllResults() {
358         mLogger = new BackupRestoreEventLogger(BACKUP);
359         mLogger.logItemsBackedUp(DATA_TYPE_1, 5);
360         mLogger.logItemsBackedUp(DATA_TYPE_2, 4);
361         mLogger.logItemsBackupFailed(DATA_TYPE_2, 1, ERROR_1);
362         assertThat(mLogger.getLoggingResults()).isNotEmpty();
363 
364         mLogger.clearData();
365 
366         assertThat(mLogger.getLoggingResults()).isEmpty();
367     }
368 
getResultForDataType( BackupRestoreEventLogger logger, String dataType)369     private static DataTypeResult getResultForDataType(
370             BackupRestoreEventLogger logger, String dataType) {
371         Optional<DataTypeResult> result = getResultForDataTypeIfPresent(logger, dataType);
372         if (result.isEmpty()) {
373             fail("Failed to find result for data type: " + dataType);
374         }
375         return result.get();
376     }
377 
getResultForDataTypeIfPresent( BackupRestoreEventLogger logger, String dataType)378     private static Optional<DataTypeResult> getResultForDataTypeIfPresent(
379             BackupRestoreEventLogger logger, String dataType) {
380         List<DataTypeResult> resultList = logger.getLoggingResults();
381         return resultList.stream()
382                 .filter(dataTypeResult -> dataTypeResult.getDataType().equals(dataType))
383                 .findAny();
384     }
385 
getMetaDataHash(String metaData)386     private byte[] getMetaDataHash(String metaData) {
387         return mHashDigest.digest(metaData.getBytes(StandardCharsets.UTF_8));
388     }
389 }
390