1 /*
2  * Copyright (C) 2021 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 com.android.server.backup.internal;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.verify;
22 
23 import android.platform.test.annotations.Presubmit;
24 
25 import androidx.test.runner.AndroidJUnit4;
26 
27 import com.android.server.backup.BackupRestoreTask;
28 import com.android.server.backup.OperationStorage.OpState;
29 import com.android.server.backup.OperationStorage.OpType;
30 
31 import com.google.android.collect.Sets;
32 
33 import org.junit.After;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.mockito.Mock;
38 import org.mockito.MockitoAnnotations;
39 
40 import java.util.Set;
41 
42 @Presubmit
43 @RunWith(AndroidJUnit4.class)
44 public class LifecycleOperationStorageTest {
45     private static final int USER_ID = 0;
46     private static final int TOKEN_1 = 1;
47     private static final int TOKEN_2 = 2;
48     private static final int TOKEN_3 = 3;
49     private static final long RESULT = 123L;
50 
51     private static final String PKG_FOO = "com.android.foo";
52     private static final String PKG_BAR = "com.android.bar";
53     private static final String PKG_BAZ = "com.android.baz";
54     private static final Set<String> MULTIPLE_PKG    = Sets.newHashSet(PKG_FOO);
55     private static final Set<String> MULTIPLE_PKGS_1 = Sets.newHashSet(PKG_FOO, PKG_BAR);
56     private static final Set<String> MULTIPLE_PKGS_2 = Sets.newHashSet(PKG_BAR, PKG_BAZ);
57 
58     @Mock private BackupRestoreTask mCallback;
59     private LifecycleOperationStorage mOpStorage;
60 
61     @Before
setUp()62     public void setUp() {
63         MockitoAnnotations.initMocks(/* testClass */ this);
64         mOpStorage = new LifecycleOperationStorage(USER_ID);
65     }
66 
67     @After
tearDown()68     public void tearDown() {}
69 
70     @Test
testRegisterOperation_singleOperation()71     public void testRegisterOperation_singleOperation() throws Exception {
72         mOpStorage.registerOperation(TOKEN_1, OpState.PENDING, mCallback, OpType.BACKUP_WAIT);
73 
74         Set<Integer> tokens = mOpStorage.operationTokensForOpType(OpType.BACKUP_WAIT);
75 
76         assertThat(mOpStorage.numOperations()).isEqualTo(1);
77         assertThat(tokens).isEqualTo(only(TOKEN_1));
78     }
79 
80     @Test
testRegisterOperation_multipleOperations()81     public void testRegisterOperation_multipleOperations() throws Exception {
82         mOpStorage.registerOperation(TOKEN_1, OpState.PENDING, mCallback, OpType.BACKUP_WAIT);
83         mOpStorage.registerOperation(TOKEN_2, OpState.ACKNOWLEDGED, mCallback, OpType.BACKUP_WAIT);
84 
85         Set<Integer> typeWaitTokens = mOpStorage.operationTokensForOpType(OpType.BACKUP_WAIT);
86         Set<Integer> statePendingTokens = mOpStorage.operationTokensForOpState(OpState.PENDING);
87         Set<Integer> stateAcknowledgedTokens =
88                 mOpStorage.operationTokensForOpState(OpState.ACKNOWLEDGED);
89 
90         assertThat(mOpStorage.numOperations()).isEqualTo(2);
91         assertThat(typeWaitTokens).isEqualTo(Sets.newHashSet(TOKEN_1, TOKEN_2));
92         assertThat(statePendingTokens).isEqualTo(only(TOKEN_1));
93         assertThat(stateAcknowledgedTokens).isEqualTo(only(TOKEN_2));
94     }
95 
96     @Test
testRegisterOperationForPackages_singlePackage()97     public void testRegisterOperationForPackages_singlePackage() throws Exception {
98         mOpStorage.registerOperationForPackages(TOKEN_1, OpState.PENDING,
99                 MULTIPLE_PKG, mCallback, OpType.BACKUP_WAIT);
100 
101         Set<Integer> tokens = mOpStorage.operationTokensForPackage(PKG_FOO);
102 
103         assertThat(mOpStorage.numOperations()).isEqualTo(1);
104         assertThat(tokens).isEqualTo(only(TOKEN_1));
105     }
106 
107     @Test
testRegisterOperationForPackages_multiplePackage()108     public void testRegisterOperationForPackages_multiplePackage() throws Exception {
109         mOpStorage.registerOperationForPackages(TOKEN_1, OpState.PENDING,
110                 MULTIPLE_PKGS_1, mCallback, OpType.BACKUP);
111         mOpStorage.registerOperationForPackages(TOKEN_2, OpState.PENDING,
112                 MULTIPLE_PKGS_2, mCallback, OpType.BACKUP);
113 
114         Set<Integer> tokensFoo = mOpStorage.operationTokensForPackage(PKG_FOO);
115         Set<Integer> tokensBar = mOpStorage.operationTokensForPackage(PKG_BAR);
116         Set<Integer> tokensBaz = mOpStorage.operationTokensForPackage(PKG_BAZ);
117 
118         assertThat(mOpStorage.numOperations()).isEqualTo(2);
119         assertThat(tokensFoo).isEqualTo(only(TOKEN_1));
120         assertThat(tokensBar).isEqualTo(Sets.newHashSet(TOKEN_1, TOKEN_2));
121         assertThat(tokensBaz).isEqualTo(only(TOKEN_2));
122     }
123 
124     @Test
testRemoveOperation()125     public void testRemoveOperation() throws Exception {
126         mOpStorage.registerOperation(TOKEN_2, OpState.PENDING, mCallback, OpType.BACKUP_WAIT);
127 
128         Set<Integer> typeWaitTokens = mOpStorage.operationTokensForOpType(OpType.BACKUP_WAIT);
129         Set<Integer> statePendingTokens = mOpStorage.operationTokensForOpState(OpState.PENDING);
130 
131         assertThat(mOpStorage.numOperations()).isEqualTo(1);
132         assertThat(typeWaitTokens).isEqualTo(only(TOKEN_2));
133         assertThat(statePendingTokens).isEqualTo(only(TOKEN_2));
134 
135         mOpStorage.removeOperation(TOKEN_2);
136 
137         typeWaitTokens = mOpStorage.operationTokensForOpType(OpType.BACKUP_WAIT);
138         statePendingTokens = mOpStorage.operationTokensForOpState(OpState.PENDING);
139 
140         assertThat(mOpStorage.numOperations()).isEqualTo(0);
141         assertThat(typeWaitTokens).isEmpty();
142         assertThat(statePendingTokens).isEmpty();
143     }
144 
145     @Test
testRemoveOperation_removesPackageMappings()146     public void testRemoveOperation_removesPackageMappings() throws Exception {
147         mOpStorage.registerOperationForPackages(TOKEN_1, OpState.PENDING, MULTIPLE_PKGS_1,
148                 mCallback, OpType.BACKUP);
149         mOpStorage.registerOperationForPackages(TOKEN_2, OpState.PENDING, MULTIPLE_PKGS_2,
150                 mCallback, OpType.BACKUP);
151 
152         mOpStorage.removeOperation(TOKEN_2);
153 
154         Set<Integer> tokensFoo = mOpStorage.operationTokensForPackage(PKG_FOO);
155         Set<Integer> tokensBar = mOpStorage.operationTokensForPackage(PKG_BAR);
156         Set<Integer> tokensBaz = mOpStorage.operationTokensForPackage(PKG_BAZ);
157 
158         assertThat(mOpStorage.numOperations()).isEqualTo(1);
159         assertThat(tokensFoo).isEqualTo(only(TOKEN_1));
160         assertThat(tokensBar).isEqualTo(only(TOKEN_1));
161         assertThat(tokensBaz).isEmpty();
162     }
163 
164     @Test
testIsBackupOperationInProgress()165     public void testIsBackupOperationInProgress() throws Exception {
166         mOpStorage.registerOperation(TOKEN_1, OpState.ACKNOWLEDGED, mCallback, OpType.RESTORE_WAIT);
167         assertThat(mOpStorage.isBackupOperationInProgress()).isFalse();
168 
169         mOpStorage.registerOperation(TOKEN_2, OpState.TIMEOUT, mCallback, OpType.BACKUP_WAIT);
170         assertThat(mOpStorage.isBackupOperationInProgress()).isFalse();
171 
172         mOpStorage.registerOperation(TOKEN_3, OpState.PENDING, mCallback, OpType.BACKUP);
173         assertThat(mOpStorage.isBackupOperationInProgress()).isTrue();
174     }
175 
176     @Test
testOnOperationComplete_pendingAdvancesState_invokesCallback()177     public void testOnOperationComplete_pendingAdvancesState_invokesCallback() throws Exception {
178         mOpStorage.registerOperation(TOKEN_1, OpState.PENDING, mCallback, OpType.BACKUP_WAIT);
179 
180         mOpStorage.onOperationComplete(TOKEN_1, RESULT, callback -> {
181             mCallback.operationComplete(RESULT);
182         });
183 
184         assertThat(mOpStorage.operationTokensForOpType(OpType.BACKUP_WAIT))
185                 .isEqualTo(only(TOKEN_1));
186         assertThat(mOpStorage.operationTokensForOpState(OpState.PENDING)).isEmpty();
187         assertThat(mOpStorage.operationTokensForOpState(OpState.ACKNOWLEDGED)).isNotEmpty();
188         verify(mCallback).operationComplete(RESULT);
189     }
190 
only(Integer val)191     private Set<Integer> only(Integer val) {
192         return Sets.newHashSet(val);
193     }
194 }
195