1 /*
2  * Copyright (C) 2018 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.compatibility.common.util;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 
23 import com.android.tradefed.util.RunUtil;
24 
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.junit.runners.JUnit4;
29 
30 import java.io.ByteArrayInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 
34 /**
35  * Unit tests for {@link BackupUtils}
36  */
37 @RunWith(JUnit4.class)
38 public class BackupUtilsTest {
39     private static final int BACKUP_SERVICE_INIT_TIMEOUT_SECS = 1;
40     private static final int TEST_USER_ID = 10;
41 
42     private boolean mIsDumpsysCommandCalled;
43     private boolean mIsEnableCommandCalled;
44     private boolean mIsActivateCommandCalled;
45 
46     @Before
setUp()47     public void setUp() {
48         mIsDumpsysCommandCalled = false;
49         mIsEnableCommandCalled = false;
50     }
51 
52     @Test
testEnableBackup_whenEnableTrueAndEnabled_returnsTrue()53     public void testEnableBackup_whenEnableTrueAndEnabled_returnsTrue() throws Exception {
54         BackupUtils backupUtils = new BackupUtils() {
55             @Override
56             protected InputStream executeShellCommand(String command) throws IOException {
57                 String output = "";
58                 if (command.equals("bmgr enabled")) {
59                     output = "Backup Manager currently enabled";
60                 } else if (command.equals("bmgr enable true")) {
61                     output = "Backup Manager now enabled";
62                     mIsEnableCommandCalled = true;
63                 }
64                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
65             }
66         };
67         assertTrue(backupUtils.enableBackup(true));
68         assertTrue(mIsEnableCommandCalled);
69     }
70 
71     @Test
testEnableBackup_whenEnableTrueAndDisabled_returnsFalse()72     public void testEnableBackup_whenEnableTrueAndDisabled_returnsFalse() throws Exception {
73         BackupUtils backupUtils = new BackupUtils() {
74             @Override
75             protected InputStream executeShellCommand(String command) throws IOException {
76                 String output = "";
77                 if (command.equals("bmgr enabled")) {
78                     output = "Backup Manager currently disabled";
79                 } else if (command.equals("bmgr enable true")) {
80                     output = "Backup Manager now enabled";
81                     mIsEnableCommandCalled = true;
82                 }
83                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
84             }
85         };
86         assertFalse(backupUtils.enableBackup(true));
87         assertTrue(mIsEnableCommandCalled);
88     }
89 
90     @Test
testEnableBackup_whenEnableFalseAndEnabled_returnsTrue()91     public void testEnableBackup_whenEnableFalseAndEnabled_returnsTrue() throws Exception {
92         BackupUtils backupUtils = new BackupUtils() {
93             @Override
94             protected InputStream executeShellCommand(String command) throws IOException {
95                 String output = "";
96                 if (command.equals("bmgr enabled")) {
97                     output = "Backup Manager currently enabled";
98                 } else if (command.equals("bmgr enable false")) {
99                     output = "Backup Manager now disabled";
100                     mIsEnableCommandCalled = true;
101                 }
102                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
103             }
104         };
105         assertTrue(backupUtils.enableBackup(false));
106         assertTrue(mIsEnableCommandCalled);
107     }
108 
109     @Test
testEnableBackup_whenEnableFalseAndDisabled_returnsFalse()110     public void testEnableBackup_whenEnableFalseAndDisabled_returnsFalse() throws Exception {
111         BackupUtils backupUtils = new BackupUtils() {
112             @Override
113             protected InputStream executeShellCommand(String command) throws IOException {
114                 String output = "";
115                 if (command.equals("bmgr enabled")) {
116                     output = "Backup Manager currently disabled";
117                 } else if (command.equals("bmgr enable false")) {
118                     output = "Backup Manager now disabled";
119                     mIsEnableCommandCalled = true;
120                 }
121                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
122             }
123         };
124         assertFalse(backupUtils.enableBackup(false));
125         assertTrue(mIsEnableCommandCalled);
126     }
127 
128     @Test
testEnableBackup_whenEnableTrueAndEnabledAndCommandsReturnMultipleLines()129     public void testEnableBackup_whenEnableTrueAndEnabledAndCommandsReturnMultipleLines()
130             throws Exception {
131         BackupUtils backupUtils = new BackupUtils() {
132             @Override
133             protected InputStream executeShellCommand(String command) throws IOException {
134                 String output = "";
135                 if (command.equals("bmgr enabled")) {
136                     output = "Backup Manager currently enabled" + "\n...";
137                 } else if (command.equals("bmgr enable true")) {
138                     output = "Backup Manager now enabled" + "\n...";
139                     mIsEnableCommandCalled = true;
140                 }
141                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
142             }
143         };
144         assertTrue(backupUtils.enableBackup(true));
145         assertTrue(mIsEnableCommandCalled);
146     }
147 
148     @Test
testEnableBackup_whenQueryCommandThrows_propagatesException()149     public void testEnableBackup_whenQueryCommandThrows_propagatesException() throws Exception {
150         BackupUtils backupUtils = new BackupUtils() {
151             @Override
152             protected InputStream executeShellCommand(String command) throws IOException {
153                 String output = "";
154                 if (command.equals("bmgr enabled")) {
155                     throw new IOException(String.format(
156                             "enableBackup: Failed to run command: %s", command));
157                 } else if (command.equals("bmgr enable true")) {
158                     output = "Backup Manager now enabled";
159                     mIsEnableCommandCalled = true;
160                 }
161                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
162             }
163         };
164 
165         boolean isExceptionHappened = false;
166         try {
167             backupUtils.enableBackup(true);
168         } catch (IOException e) {
169             // enableBackup: Failed to run command: bmgr enabled
170             isExceptionHappened = true;
171         }
172         assertTrue(isExceptionHappened);
173         assertFalse(mIsEnableCommandCalled);
174     }
175 
176     @Test
testEnableBackup_whenSetCommandThrows_propagatesException()177     public void testEnableBackup_whenSetCommandThrows_propagatesException() throws Exception {
178         BackupUtils backupUtils = new BackupUtils() {
179             @Override
180             protected InputStream executeShellCommand(String command) throws IOException {
181                 String output = "";
182                 if (command.equals("bmgr enabled")) {
183                     output = "Backup Manager currently enabled";
184                 } else if (command.equals("bmgr enable true")) {
185                     mIsEnableCommandCalled = true;
186                     throw new IOException(String.format(
187                             "enableBackup: Failed to run command: %s", command));
188                 }
189                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
190             }
191         };
192 
193         boolean isExceptionHappened = false;
194         try {
195             backupUtils.enableBackup(true);
196         } catch (IOException e) {
197             // enableBackup: Failed to run command: bmgr enable true
198             isExceptionHappened = true;
199         }
200         assertTrue(isExceptionHappened);
201         assertTrue(mIsEnableCommandCalled);
202     }
203 
204     @Test
testEnableBackup_whenQueryCommandReturnsInvalidString_throwsException()205     public void testEnableBackup_whenQueryCommandReturnsInvalidString_throwsException()
206             throws Exception {
207         BackupUtils backupUtils = new BackupUtils() {
208             @Override
209             protected InputStream executeShellCommand(String command) throws IOException {
210                 String output = "";
211                 if (command.equals("bmgr enabled")) {
212                     output = "Backup Manager ???";
213                 } else if (command.equals("bmgr enable true")) {
214                     output = "Backup Manager now enabled";
215                     mIsEnableCommandCalled = true;
216                 }
217                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
218             }
219         };
220 
221         boolean isExceptionHappened = false;
222         try {
223             backupUtils.enableBackup(true);
224         } catch (RuntimeException e) {
225             // non-parsable output setting bmgr enabled: Backup Manager ???
226             isExceptionHappened = true;
227         }
228         assertTrue(isExceptionHappened);
229         assertFalse(mIsEnableCommandCalled);
230     }
231 
232     @Test
testEnableBackup_whenQueryCommandReturnsEmptyString_throwsException()233     public void testEnableBackup_whenQueryCommandReturnsEmptyString_throwsException()
234             throws Exception {
235         BackupUtils backupUtils = new BackupUtils() {
236             @Override
237             protected InputStream executeShellCommand(String command) throws IOException {
238                 String output = "";
239                 if (command.equals("bmgr enabled")) {
240                     // output is empty already
241                 } else if (command.equals("bmgr enable true")) {
242                     output = "Backup Manager now enabled";
243                     mIsEnableCommandCalled = true;
244                 }
245                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
246             }
247         };
248 
249         boolean isExceptionHappened = false;
250         try {
251             backupUtils.enableBackup(true);
252         } catch (NullPointerException e) {
253             // null output by running command, bmgr enabled
254             isExceptionHappened = true;
255         }
256         assertTrue(isExceptionHappened);
257         assertFalse(mIsEnableCommandCalled);
258     }
259 
260     @Test
testWaitForBackupInitialization_whenEnabled()261     public void testWaitForBackupInitialization_whenEnabled() throws Exception {
262         BackupUtils backupUtils = new BackupUtils() {
263             @Override
264             protected InputStream executeShellCommand(String command) throws IOException {
265                 String output = "";
266                 if (command.equals("dumpsys backup")) {
267                     output = "Backup Manager is enabled / provisioned / not pending init";
268                     mIsDumpsysCommandCalled = true;
269                 }
270                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
271             }
272         };
273         backupUtils.waitForBackupInitialization();
274         assertTrue(mIsDumpsysCommandCalled);
275     }
276 
277     @Test
testWaitForBackupInitialization_whenDisabled()278     public void testWaitForBackupInitialization_whenDisabled() throws Exception {
279         BackupUtils backupUtils = new BackupUtils() {
280             @Override
281             protected InputStream executeShellCommand(String command) throws IOException {
282                 String output = "";
283                 if (command.equals("dumpsys backup")) {
284                     output = "Backup Manager is disabled / provisioned / not pending init";
285                     mIsDumpsysCommandCalled = true;
286                 }
287                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
288             }
289         };
290         backupUtils.waitForBackupInitialization();
291         assertTrue(mIsDumpsysCommandCalled);
292     }
293 
294     @Test
testWaitUntilBackupServiceIsRunning_whenRunning_doesntThrow()295     public void testWaitUntilBackupServiceIsRunning_whenRunning_doesntThrow() throws Exception {
296         BackupUtils backupUtils = constructDumpsysForBackupUsers(TEST_USER_ID);
297 
298         try {
299             backupUtils.waitUntilBackupServiceIsRunning(
300                     TEST_USER_ID, BACKUP_SERVICE_INIT_TIMEOUT_SECS);
301         } catch (AssertionError e) {
302             fail("BackupUtils#waitUntilBackupServiceIsRunning threw an exception");
303         }
304         assertTrue(mIsDumpsysCommandCalled);
305     }
306 
307     @Test
testWaitUntilBackupServiceIsRunning_whenNotRunning_throws()308     public void testWaitUntilBackupServiceIsRunning_whenNotRunning_throws() throws Exception {
309         // Pass in a different userId to not have the current one among running ids.
310         BackupUtils backupUtils = constructDumpsysForBackupUsers(TEST_USER_ID + 1);
311 
312         boolean wasExceptionThrown = false;
313         try {
314             backupUtils.waitUntilBackupServiceIsRunning(
315                     TEST_USER_ID, BACKUP_SERVICE_INIT_TIMEOUT_SECS);
316         } catch (AssertionError e) {
317             wasExceptionThrown = true;
318         }
319 
320         assertTrue(mIsDumpsysCommandCalled);
321         assertTrue(wasExceptionThrown);
322     }
323 
constructDumpsysForBackupUsers(int runningUserId)324     private BackupUtils constructDumpsysForBackupUsers(int runningUserId) {
325         return new BackupUtils() {
326             @Override
327             protected InputStream executeShellCommand(String command) throws IOException {
328                 String output = "";
329                 if (command.equals("dumpsys backup users")) {
330                     output = "Backup Manager is running for users: " + runningUserId;
331                     mIsDumpsysCommandCalled = true;
332                 }
333                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
334             }
335         };
336     }
337 
338     @Test
339     public void testWaitForBackupInitialization_whenEnabledAndCommandReturnsMultipleLines()
340             throws Exception {
341         BackupUtils backupUtils = new BackupUtils() {
342             @Override
343             protected InputStream executeShellCommand(String command) throws IOException {
344                 String output = "";
345                 if (command.equals("dumpsys backup")) {
346                     output = "Backup Manager is enabled / provisioned / not pending init" + "\n...";
347                     mIsDumpsysCommandCalled = true;
348                 }
349                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
350             }
351         };
352         backupUtils.waitForBackupInitialization();
353         assertTrue(mIsDumpsysCommandCalled);
354     }
355 
356     @Test
357     public void testWaitForBackupInitialization_whenCommandThrows_propagatesException()
358             throws Exception {
359         BackupUtils backupUtils = new BackupUtils() {
360             @Override
361             protected InputStream executeShellCommand(String command) throws IOException {
362                 String output = "";
363                 if (command.equals("dumpsys backup")) {
364                     mIsDumpsysCommandCalled = true;
365                     throw new IOException(String.format(
366                             "waitForBackupInitialization: Failed to run command: %s", command));
367                 }
368                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
369             }
370         };
371 
372         boolean isExceptionHappened = false;
373         try {
374             backupUtils.waitForBackupInitialization();
375         } catch (IOException e) {
376             // waitForBackupInitialization: Failed to run command: dumpsys backup
377             isExceptionHappened = true;
378         }
379         assertTrue(isExceptionHappened);
380         assertTrue(mIsDumpsysCommandCalled);
381     }
382 
383     @Test
384     public void testWaitForBackupInitialization_whenCommandReturnsInvalidString()
385             throws Exception {
386         class TestRunnable implements Runnable {
387             @Override
388             public void run() {
389                 try {
390                     BackupUtils backupUtils = new BackupUtils() {
391                         @Override
392                         protected InputStream executeShellCommand(String command)
393                                 throws IOException {
394                             String output = "";
395                             if (command.equals("dumpsys backup")) {
396                                 output = "Backup Manager ???";
397                                 mIsDumpsysCommandCalled = true;
398                             }
399                             return new ByteArrayInputStream(output.getBytes("UTF-8"));
400                         }
401                     };
402                     backupUtils.waitForBackupInitialization();
403                 } catch (IOException e) {
404                     // ignore
405                 }
406             }
407         }
408 
409         TestRunnable testRunnable = new TestRunnable();
410         Thread testThread = new Thread(testRunnable);
411 
412         try {
413             testThread.start();
414             RunUtil.getDefault().sleep(100);
415             assertTrue(mIsDumpsysCommandCalled);
416             assertTrue(testThread.isAlive());
417         } catch (Exception e) {
418             // ignore
419         } finally {
420             testThread.interrupt();
421         }
422     }
423 
424     @Test
425     public void testWaitForBackupInitialization_whenCommandReturnsEmptyString_throwsException()
426             throws Exception {
427         BackupUtils backupUtils = new BackupUtils() {
428             @Override
429             protected InputStream executeShellCommand(String command) throws IOException {
430                 String output = "";
431                 if (command.equals("dumpsys backup")) {
432                     // output is empty already
433                     mIsDumpsysCommandCalled = true;
434                 }
435                 return new ByteArrayInputStream(output.getBytes("UTF-8"));
436             }
437         };
438 
439         boolean isExceptionHappened = false;
440         try {
441             backupUtils.waitForBackupInitialization();
442         } catch (NullPointerException e) {
443             // null output by running command, dumpsys backup
444             isExceptionHappened = true;
445         }
446         assertTrue(isExceptionHappened);
447         assertTrue(mIsDumpsysCommandCalled);
448     }
449 
450     @Test
451     public void testActivateBackup_whenEnableTrueAndEnabled_returnsTrue() throws Exception {
452         BackupUtils backupUtils =
453                 new BackupUtils() {
454                     @Override
455                     protected InputStream executeShellCommand(String command) throws IOException {
456                         String output = "";
457                         if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
458                             output = "Backup Manager currently activated";
459                         } else if (command.equals(getBmgrCommand("activate true", TEST_USER_ID))) {
460                             output = "Backup Manager now activated";
461                             mIsActivateCommandCalled = true;
462                         }
463                         return new ByteArrayInputStream(output.getBytes("UTF-8"));
464                     }
465                 };
466         assertTrue(backupUtils.activateBackupForUser(true, TEST_USER_ID));
467         assertTrue(mIsActivateCommandCalled);
468     }
469 
470     @Test
471     public void testActivateBackup_whenEnableTrueAndDisabled_returnsFalse() throws Exception {
472         BackupUtils backupUtils =
473                 new BackupUtils() {
474                     @Override
475                     protected InputStream executeShellCommand(String command) throws IOException {
476                         String output = "";
477                         if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
478                             output = "Backup Manager currently deactivated";
479                         } else if (command.equals(getBmgrCommand("activate true", TEST_USER_ID))) {
480                             output = "Backup Manager now activated";
481                             mIsActivateCommandCalled = true;
482                         }
483                         return new ByteArrayInputStream(output.getBytes("UTF-8"));
484                     }
485                 };
486         assertFalse(backupUtils.activateBackupForUser(true, TEST_USER_ID));
487         assertTrue(mIsActivateCommandCalled);
488     }
489 
490     @Test
491     public void testActivateBackup_whenEnableFalseAndEnabled_returnsTrue() throws Exception {
492         BackupUtils backupUtils =
493                 new BackupUtils() {
494                     @Override
495                     protected InputStream executeShellCommand(String command) throws IOException {
496                         String output = "";
497                         if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
498                             output = "Backup Manager currently activated";
499                         } else if (command.equals(getBmgrCommand("activate false", TEST_USER_ID))) {
500                             output = "Backup Manager now deactivated";
501                             mIsActivateCommandCalled = true;
502                         }
503                         return new ByteArrayInputStream(output.getBytes("UTF-8"));
504                     }
505                 };
506         assertTrue(backupUtils.activateBackupForUser(false, TEST_USER_ID));
507         assertTrue(mIsActivateCommandCalled);
508     }
509 
510     @Test
511     public void testActivateBackup_whenEnableFalseAndDisabled_returnsFalse() throws Exception {
512         BackupUtils backupUtils =
513                 new BackupUtils() {
514                     @Override
515                     protected InputStream executeShellCommand(String command) throws IOException {
516                         String output = "";
517                         if (command.equals(getBmgrCommand("activated", TEST_USER_ID))) {
518                             output = "Backup Manager currently deactivated";
519                         } else if (command.equals(getBmgrCommand("activate false", TEST_USER_ID))) {
520                             output = "Backup Manager now deactivated";
521                             mIsActivateCommandCalled = true;
522                         }
523                         return new ByteArrayInputStream(output.getBytes("UTF-8"));
524                     }
525                 };
526         assertFalse(backupUtils.activateBackupForUser(false, TEST_USER_ID));
527         assertTrue(mIsActivateCommandCalled);
528     }
529 
530     private String getBmgrCommand(String command, int userId) {
531         return "bmgr --user " + userId + " " + command;
532     }
533 }
534