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