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 
17 package com.android.documentsui.prefs;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.fail;
22 
23 import android.content.SharedPreferences;
24 import android.content.SharedPreferences.Editor;
25 
26 import androidx.test.InstrumentationRegistry;
27 import androidx.test.filters.SmallTest;
28 import androidx.test.runner.AndroidJUnit4;
29 
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Set;
39 
40 @RunWith(AndroidJUnit4.class)
41 @SmallTest
42 public class PrefsBackupHelperTest {
43 
44     private static final String LOCAL_PREFERENCE_1 = "rootViewMode-validPreference1";
45     private static final String LOCAL_PREFERENCE_2 = "rootViewMode-validPreference2";
46     private static final String NON_BACKUP_PREFERENCE = "notBackup-invalidPreference";
47 
48     private SharedPreferences mDefaultPrefs;
49     private SharedPreferences mBackupPrefs;
50     private PrefsBackupHelper mPrefsBackupHelper;
51 
52     @Before
setUp()53     public void setUp() {
54         mDefaultPrefs = InstrumentationRegistry.getContext().getSharedPreferences("prefs1", 0);
55         mBackupPrefs = InstrumentationRegistry.getContext().getSharedPreferences("prefs2", 0);
56         clearSharedPrefs();
57         mPrefsBackupHelper = new PrefsBackupHelper(mDefaultPrefs);
58     }
59 
60     @After
tearDown()61     public void tearDown() {
62         clearSharedPrefs();
63     }
64 
clearSharedPrefs()65     private void clearSharedPrefs() {
66         mDefaultPrefs.edit().clear().commit();
67         mBackupPrefs.edit().clear().commit();
68     }
69 
70     @Test
testPrepareBackupFile_BackupLocalPreferences()71     public void testPrepareBackupFile_BackupLocalPreferences() {
72         mDefaultPrefs.edit().putInt(LOCAL_PREFERENCE_1, 1).commit();
73 
74         mPrefsBackupHelper.getBackupPreferences(mBackupPrefs);
75 
76         assertEquals(mBackupPrefs.getInt(LOCAL_PREFERENCE_1, 0), 1);
77     }
78 
79     @Test
testPrepareBackupFile_BackupNotInterestedPreferences()80     public void testPrepareBackupFile_BackupNotInterestedPreferences() {
81         mDefaultPrefs.edit().putBoolean(NON_BACKUP_PREFERENCE, true).commit();
82 
83         mPrefsBackupHelper.getBackupPreferences(mBackupPrefs);
84 
85         assertFalse(mBackupPrefs.contains(NON_BACKUP_PREFERENCE));
86     }
87 
88     @Test
testPrepareBackupFile_BackupUnexpectedType()89     public void testPrepareBackupFile_BackupUnexpectedType() throws Exception {
90         // Currently only Integer and Boolean type are supported.
91         mDefaultPrefs.edit().putString(LOCAL_PREFERENCE_1, "String is not accepted").commit();
92 
93         try {
94             mPrefsBackupHelper.getBackupPreferences(mBackupPrefs);
95             fail();
96         } catch(IllegalArgumentException e) {
97 
98         } finally {
99             assertFalse(mBackupPrefs.contains(LOCAL_PREFERENCE_1));
100         }
101     }
102 
103     @Test
testRestorePreferences_RestoreLocalPreferences()104     public void testRestorePreferences_RestoreLocalPreferences() {
105         mBackupPrefs.edit().putInt(LOCAL_PREFERENCE_1, 1).commit();
106 
107         mPrefsBackupHelper.putBackupPreferences(mBackupPrefs);
108 
109         assertEquals(mDefaultPrefs.getInt(LOCAL_PREFERENCE_1, 0), 1);
110     }
111 
112     @Test
testEndToEnd()113     public void testEndToEnd() {
114         // Simulating an end to end backup & restore process. At the begining, all preferences are
115         // stored in the default shared preferences file, includes preferences that we don't want
116         // to backup.
117         //
118         // On backup, we copy all preferences that we want to backup to the backup shared
119         // preferences file, and then backup that single file.
120         //
121         // On restore, we restore the backup file first, and then copy all preferences in the backup
122         // file to the app's default shared preferences file.
123 
124         SharedPreferences.Editor editor = mDefaultPrefs.edit();
125 
126         // Set preferences to the default file, includes preferences that are not backed up.
127         editor.putInt(LOCAL_PREFERENCE_1, 1);
128         editor.putInt(LOCAL_PREFERENCE_2, 2);
129         editor.putBoolean(NON_BACKUP_PREFERENCE, true);
130         editor.commit();
131 
132         // Write all backed up preferences to backup shared preferences file.
133         mPrefsBackupHelper.getBackupPreferences(mBackupPrefs);
134 
135         // Assume we are doing backup to the backup file.
136 
137         // Clear all preferences in default shared preferences file.
138         editor.clear().commit();
139 
140         // Assume we are doing restore to the backup file.
141 
142         // Copy all backuped preferences to default shared preferences file.
143         mPrefsBackupHelper.putBackupPreferences(mBackupPrefs);
144 
145         // Check all preferences are correctly restored.
146         assertEquals(mDefaultPrefs.getInt(LOCAL_PREFERENCE_1, 0), 1);
147         assertEquals(mDefaultPrefs.getInt(LOCAL_PREFERENCE_2, 0), 2);
148         assertFalse(mDefaultPrefs.contains(NON_BACKUP_PREFERENCE));
149     }
150 
151     @Test
testPreferenceTypesSupport()152     public void testPreferenceTypesSupport() {
153         Map<String, Object> map = new HashMap<String, Object>();
154         map.put("int", (Integer) 1);
155         map.put("float", (Float) 0.1f);
156         map.put("long", (Long) 10000000000l);
157         map.put("boolean", true);
158         map.put("String", "String");
159         Set<String> stringSet = new HashSet<String>();
160         stringSet.add("string1");
161         stringSet.add("string2");
162         map.put("StringSet", stringSet);
163 
164         // SharedPreferences accept Integer, Float, Long, Boolean, String, Set<String> types.
165         // Currently in DocumentsUI, only Integer and Boolean preferences are backed up.
166         for (Map.Entry<String, ?> entry : map.entrySet()) {
167             String key = entry.getKey();
168             Object value = entry.getValue();
169             Editor editor = mDefaultPrefs.edit().clear();
170             if (value instanceof Integer) {
171                 mPrefsBackupHelper.setPreference(editor, entry);
172                 editor.apply();
173                 assertEquals(mDefaultPrefs.getInt("int", 0), 1);
174             } else if(value instanceof Boolean) {
175                 mPrefsBackupHelper.setPreference(editor, entry);
176                 editor.apply();
177                 assertEquals(mDefaultPrefs.getBoolean("boolean", false), true);
178             } else {
179                 try {
180                     mPrefsBackupHelper.setPreference(editor, entry);
181                     fail();
182                 } catch(IllegalArgumentException e) {
183 
184                 } finally {
185                     editor.apply();
186                     assertFalse(mDefaultPrefs.contains(key));
187                 }
188             }
189         }
190     }
191 }
192