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