• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.providers.contacts;
18 
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.database.DatabaseUtils;
22 import android.database.sqlite.SQLiteDatabase;
23 import android.net.Uri;
24 import android.provider.BaseColumns;
25 import android.provider.CallLog;
26 import android.provider.CallLog.Calls;
27 import android.provider.ContactsContract.Contacts;
28 import android.provider.ContactsContract.Data;
29 import android.provider.ContactsContract.Groups;
30 import android.provider.ContactsContract.RawContacts;
31 import android.test.mock.MockContext;
32 import android.test.suitebuilder.annotation.MediumTest;
33 
34 import java.io.ByteArrayOutputStream;
35 import java.io.File;
36 import java.io.IOException;
37 import java.io.InputStream;
38 
39 /**
40  * Unit tests for {@link LegacyContactImporter}.
41  *
42  * Run the test like this:
43  * <code>
44  * adb shell am instrument -e class com.android.providers.contacts.LegacyContactImporterTest -w \
45  *         com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
46  * </code>
47  *
48  * Note that this SHOULD be a large test, but had to be bumped down to medium due to a bug in the
49  * SQLite cleanup code.
50  */
51 @MediumTest
52 public class LegacyContactImporterTest extends BaseContactsProvider2Test {
53 
54     private static class LegacyMockContext extends MockContext {
55 
56         private String mFileName;
57 
LegacyMockContext(String fileName)58         public LegacyMockContext(String fileName) {
59             mFileName = fileName;
60         }
61 
62         @Override
openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory)63         public SQLiteDatabase openOrCreateDatabase(String file, int mode,
64                 SQLiteDatabase.CursorFactory factory) {
65             return SQLiteDatabase.openDatabase(mFileName, factory, SQLiteDatabase.OPEN_READONLY);
66         }
67 
68         @Override
getDatabasePath(String name)69         public File getDatabasePath(String name) {
70             return new File(mFileName);
71         }
72     }
73 
createLegacyMockContext(String folder)74     private LegacyMockContext createLegacyMockContext(String folder) throws IOException {
75         Context context = getTestContext();
76         File tempDb = new File(context.getFilesDir(), "legacy_contacts.db");
77         if (tempDb.exists()) {
78             tempDb.delete();
79         }
80         createSQLiteDatabaseFromDumpFile(tempDb.getPath(),
81                 new File(folder, "legacy_contacts.sql").getPath());
82         return new LegacyMockContext(tempDb.getPath());
83     }
84 
createSQLiteDatabaseFromDumpFile(String tempDbPath, String dumpFileAssetPath)85     private void createSQLiteDatabaseFromDumpFile(String tempDbPath, String dumpFileAssetPath)
86         throws IOException {
87 
88         final String[] ignoredTables = new String[] {"android_metadata", "sqlite_sequence"};
89 
90         Context context = getTestContext();
91         SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(tempDbPath, null);
92         try {
93             String data = readAssetAsString(dumpFileAssetPath);
94             String[] commands = data.split(";\r|;\n|;\r\n");
95             for (String command : commands) {
96                 boolean ignore = false;
97                 for (String ignoredTable : ignoredTables) {
98                     if (command.contains(ignoredTable)) {
99                         ignore = true;
100                         break;
101                     }
102                 }
103                 if (!ignore) {
104                     database.execSQL(command);
105                 }
106             }
107 
108             assertTrue(
109                     "Database Version not set. Be sure to add " +
110                     "'PRAGMA user_version = <number>;' to the SQL Script",
111                     database.getVersion() != 0);
112         } finally {
113             database.close();
114         }
115     }
116 
117     @Override
setUp()118     protected void setUp() throws Exception {
119         SynchronousContactsProvider2.resetOpenHelper();
120         super.setUp();
121         addProvider(TestCallLogProvider.class, CallLog.AUTHORITY);
122     }
123 
124     @Override
tearDown()125     protected void tearDown() throws Exception {
126         super.tearDown();
127         SynchronousContactsProvider2.resetOpenHelper();
128     }
129 
testContactUpgrade1()130     public void testContactUpgrade1() throws Exception {
131         testAssetSet("test1");
132     }
133 
testSyncedContactsUpgrade()134     public void testSyncedContactsUpgrade() throws Exception {
135         testAssetSet("testSynced");
136     }
137 
testUnsyncedContactsUpgrade()138     public void testUnsyncedContactsUpgrade() throws Exception {
139         testAssetSet("testUnsynced");
140     }
141 
testAssetSet(String folder)142     private void testAssetSet(String folder) throws Exception {
143         ContactsProvider2 provider = (ContactsProvider2)getProvider();
144         LegacyContactImporter importer =
145                 new LegacyContactImporter(createLegacyMockContext(folder), provider);
146         provider.importLegacyContacts(importer);
147 
148         assertQueryResults(folder + "/expected_groups.txt", Groups.CONTENT_URI, new String[]{
149                 Groups._ID,
150                 Groups.ACCOUNT_NAME,
151                 Groups.ACCOUNT_TYPE,
152                 Groups.DIRTY,
153                 Groups.GROUP_VISIBLE,
154                 Groups.NOTES,
155                 Groups.RES_PACKAGE,
156                 Groups.SOURCE_ID,
157                 Groups.SYSTEM_ID,
158                 Groups.TITLE,
159                 Groups.VERSION,
160                 Groups.SYNC1,
161                 Groups.SYNC2,
162                 Groups.SYNC3,
163                 Groups.SYNC4,
164         });
165 
166         assertQueryResults(folder + "/expected_contacts.txt", Contacts.CONTENT_URI, new String[]{
167                 Contacts._ID,
168                 Contacts.DISPLAY_NAME_PRIMARY,
169                 Contacts.SORT_KEY_PRIMARY,
170                 Contacts.PHOTO_ID,
171                 Contacts.TIMES_CONTACTED,
172                 Contacts.LAST_TIME_CONTACTED,
173                 Contacts.CUSTOM_RINGTONE,
174                 Contacts.SEND_TO_VOICEMAIL,
175                 Contacts.STARRED,
176                 Contacts.IN_VISIBLE_GROUP,
177                 Contacts.HAS_PHONE_NUMBER,
178                 Contacts.IS_USER_PROFILE,
179                 Contacts.LOOKUP_KEY,
180         });
181 
182         assertQueryResults(folder + "/expected_raw_contacts.txt", RawContacts.CONTENT_URI,
183                 new String[]{
184                     RawContacts._ID,
185                     RawContacts.ACCOUNT_NAME,
186                     RawContacts.ACCOUNT_TYPE,
187                     RawContacts.DELETED,
188                     RawContacts.DIRTY,
189                     RawContacts.SOURCE_ID,
190                     RawContacts.VERSION,
191                     RawContacts.SYNC1,
192                     RawContacts.SYNC2,
193                     RawContacts.SYNC3,
194                     RawContacts.SYNC4,
195                     RawContacts.DISPLAY_NAME_SOURCE,
196                     RawContacts.DISPLAY_NAME_PRIMARY,
197                     RawContacts.DISPLAY_NAME_ALTERNATIVE,
198                     RawContacts.SORT_KEY_PRIMARY,
199                     RawContacts.SORT_KEY_ALTERNATIVE,
200         });
201 
202         assertQueryResults(folder + "/expected_data.txt", Data.CONTENT_URI, new String[]{
203                 Data._ID,
204                 Data.RAW_CONTACT_ID,
205                 Data.MIMETYPE,
206                 Data.DATA1,
207                 Data.DATA2,
208                 Data.DATA3,
209                 Data.DATA4,
210                 Data.DATA5,
211                 Data.DATA6,
212                 Data.DATA7,
213                 Data.DATA8,
214                 Data.DATA9,
215                 Data.DATA10,
216                 Data.DATA11,
217                 Data.DATA12,
218                 Data.DATA13,
219                 Data.DATA14,
220                 Data.DATA15,
221                 Data.IS_PRIMARY,
222                 Data.IS_SUPER_PRIMARY,
223                 Data.DATA_VERSION,
224                 Data.SYNC1,
225                 Data.SYNC2,
226                 Data.SYNC3,
227                 Data.SYNC4,
228         });
229 
230         assertQueryResults(folder + "/expected_calls.txt", Calls.CONTENT_URI, new String[]{
231                 Calls._ID,
232                 Calls.NUMBER,
233                 Calls.DATE,
234                 Calls.DURATION,
235                 Calls.NEW,
236                 Calls.TYPE,
237                 Calls.CACHED_NAME,
238                 Calls.CACHED_NUMBER_LABEL,
239                 Calls.CACHED_NUMBER_TYPE,
240         });
241 
242         provider.getDatabaseHelper().close();
243     }
244 
assertQueryResults(String fileName, Uri uri, String[] projection)245     private void assertQueryResults(String fileName, Uri uri, String[] projection)
246             throws Exception {
247         String expected = readAssetAsString(fileName).trim();
248         String actual = dumpCursorToString(uri, projection).trim();
249         assertEquals("Checking golden file " + fileName, expected, actual);
250     }
251 
readAssetAsString(String fileName)252     private String readAssetAsString(String fileName) throws IOException {
253         Context context = getTestContext();
254         InputStream input = context.getAssets().open(fileName);
255         ByteArrayOutputStream contents = new ByteArrayOutputStream();
256         int len;
257         byte[] data = new byte[1024];
258         do {
259             len = input.read(data);
260             if (len > 0) contents.write(data, 0, len);
261         } while (len == data.length);
262         return contents.toString();
263     }
264 
dumpCursorToString(Uri uri, String[] projection)265     private String dumpCursorToString(Uri uri, String[] projection) {
266         Cursor c = mResolver.query(uri, projection, null, null, BaseColumns._ID);
267         if (c == null) {
268             return "Null cursor";
269         }
270 
271         String cursorDump = DatabaseUtils.dumpCursorToString(c);
272         c.close();
273         return insertLineNumbers(cursorDump);
274     }
275 
insertLineNumbers(String multiline)276     private String insertLineNumbers(String multiline) {
277         String[] lines = multiline.split("\n");
278         StringBuilder sb = new StringBuilder();
279 
280         // Ignore the first line that is a volatile header and the last line which is "<<<<<"
281         for (int i = 1; i < lines.length - 1; i++) {
282             sb.append(i).append(" ").append(lines[i]).append('\n');
283         }
284         return sb.toString();
285     }
286 
287 
288     public static class TestCallLogProvider extends CallLogProvider {
289         private static ContactsDatabaseHelper mDbHelper;
290 
291         @Override
getDatabaseHelper(final Context context)292         protected ContactsDatabaseHelper getDatabaseHelper(final Context context) {
293             if (mDbHelper == null) {
294                 mDbHelper = new ContactsDatabaseHelper(context);
295             }
296             return mDbHelper;
297         }
298     }
299 }
300