blob: 0ddeb67550b1109644ebf6e854a48ea86efcd14b [file] [log] [blame]
Chiao Chenge88fcd32012-11-13 18:38:05 -08001/*
2 * Copyright (C) 2011 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
17package com.android.contacts.common.model.account;
18
19import android.content.Context;
20import android.provider.ContactsContract.CommonDataKinds.Email;
21import android.provider.ContactsContract.CommonDataKinds.Event;
22import android.provider.ContactsContract.CommonDataKinds.Im;
23import android.provider.ContactsContract.CommonDataKinds.Note;
24import android.provider.ContactsContract.CommonDataKinds.Organization;
25import android.provider.ContactsContract.CommonDataKinds.Photo;
26import android.provider.ContactsContract.CommonDataKinds.Relation;
27import android.provider.ContactsContract.CommonDataKinds.SipAddress;
28import android.provider.ContactsContract.CommonDataKinds.StructuredName;
29import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
30import android.provider.ContactsContract.CommonDataKinds.Website;
Jay Shrauner7bae0632015-08-27 16:23:44 -070031import android.test.InstrumentationTestCase;
Chiao Chenge88fcd32012-11-13 18:38:05 -080032import android.test.suitebuilder.annotation.SmallTest;
Brandon Maxwell22f3d092015-11-11 17:46:46 -080033import android.test.suitebuilder.annotation.Suppress;
Chiao Chenge88fcd32012-11-13 18:38:05 -080034
35import com.android.contacts.common.model.dataitem.DataKind;
Yorke Leed0a33882015-10-28 18:26:19 -070036import com.android.contacts.common.tests.R;
Gary Mai7a6daea2016-10-10 15:41:48 -070037
Chiao Chenge88fcd32012-11-13 18:38:05 -080038import com.google.common.base.Objects;
39
Gary Mai7a6daea2016-10-10 15:41:48 -070040import java.util.ArrayList;
41import java.util.Arrays;
Chiao Chenge88fcd32012-11-13 18:38:05 -080042import java.util.List;
43
44/**
45 * Test case for {@link com.android.contacts.common.model.account.ExternalAccountType}.
46 *
47 * adb shell am instrument -w -e class com.android.contacts.model.ExternalAccountTypeTest \
48 com.android.contacts.tests/android.test.InstrumentationTestRunner
49 */
50@SmallTest
Jay Shrauner7bae0632015-08-27 16:23:44 -070051public class ExternalAccountTypeTest extends InstrumentationTestCase {
Gary Mai7a6daea2016-10-10 15:41:48 -070052 private static ArrayList<String> mDefaultMimetypes = new ArrayList<>(Arrays.asList(
53 StructuredName.CONTENT_ITEM_TYPE,
54 DataKind.PSEUDO_MIME_TYPE_NAME,
55 DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
56 Photo.CONTENT_ITEM_TYPE
57 ));
Brandon Maxwell22f3d092015-11-11 17:46:46 -080058
59 @Suppress
Chiao Chenge88fcd32012-11-13 18:38:05 -080060 public void testResolveExternalResId() {
Jay Shrauner05452582015-08-29 11:34:25 -070061 final Context c = getInstrumentation().getTargetContext();
Chiao Chenge88fcd32012-11-13 18:38:05 -080062 // In this test we use the test package itself as an external package.
Jay Shrauner7bae0632015-08-27 16:23:44 -070063 final String packageName = getInstrumentation().getContext().getPackageName();
Chiao Chenge88fcd32012-11-13 18:38:05 -080064
65 // Resource name empty.
66 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, null, packageName, ""));
67 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "", packageName, ""));
68
69 // Name doesn't begin with '@'
70 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "x", packageName, ""));
71
72 // Invalid resource name
73 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@", packageName, ""));
74 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@a", packageName, ""));
75 assertEquals(-1, ExternalAccountType.resolveExternalResId(c, "@a/b", packageName, ""));
76
77 // Valid resource name
78 assertEquals(R.string.test_string, ExternalAccountType.resolveExternalResId(c,
79 "@string/test_string", packageName, ""));
80 }
81
Wenyi Wangdaa6fb82016-11-21 15:37:36 -080082 public void testIsFromTestApp() {
83 assertTrue(ExternalAccountType.isFromTestApp("com.google.android.contacts.tests"));
84 assertFalse(ExternalAccountType.isFromTestApp("com.google.android.contacts"));
85 }
86
Chiao Chenge88fcd32012-11-13 18:38:05 -080087 /**
Walter Jang8df87f12015-07-10 12:19:24 -070088 * Initialize with an invalid package name and see if type will be initialized, but empty.
Chiao Chenge88fcd32012-11-13 18:38:05 -080089 */
90 public void testNoPackage() {
Jay Shrauner05452582015-08-29 11:34:25 -070091 final ExternalAccountType type = new ExternalAccountType(getInstrumentation().getTargetContext(),
Chiao Chenge88fcd32012-11-13 18:38:05 -080092 "!!!no such package name!!!", false);
Chiao Chenge88fcd32012-11-13 18:38:05 -080093 assertTrue(type.isInitialized());
94 }
Chiao Chenge88fcd32012-11-13 18:38:05 -080095
96 /**
97 * Initialize with the test package itself and see if EditSchema is correctly parsed.
98 */
Brandon Maxwell22f3d092015-11-11 17:46:46 -080099 @Suppress
Chiao Chenge88fcd32012-11-13 18:38:05 -0800100 public void testEditSchema() {
Jay Shrauner05452582015-08-29 11:34:25 -0700101 final ExternalAccountType type = new ExternalAccountType(getInstrumentation().getTargetContext(),
Jay Shrauner7bae0632015-08-27 16:23:44 -0700102 getInstrumentation().getContext().getPackageName(), false);
Chiao Chenge88fcd32012-11-13 18:38:05 -0800103
104 assertTrue(type.isInitialized());
105
106 // Let's just check if the DataKinds are registered.
107 assertNotNull(type.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE));
Gary Mai7a6daea2016-10-10 15:41:48 -0700108 assertNotNull(type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_NAME));
Chiao Chenge88fcd32012-11-13 18:38:05 -0800109 assertNotNull(type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME));
110 assertNotNull(type.getKindForMimetype(Email.CONTENT_ITEM_TYPE));
111 assertNotNull(type.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE));
112 assertNotNull(type.getKindForMimetype(Im.CONTENT_ITEM_TYPE));
113 assertNotNull(type.getKindForMimetype(Organization.CONTENT_ITEM_TYPE));
114 assertNotNull(type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE));
115 assertNotNull(type.getKindForMimetype(Note.CONTENT_ITEM_TYPE));
116 assertNotNull(type.getKindForMimetype(Website.CONTENT_ITEM_TYPE));
117 assertNotNull(type.getKindForMimetype(SipAddress.CONTENT_ITEM_TYPE));
118 assertNotNull(type.getKindForMimetype(Event.CONTENT_ITEM_TYPE));
119 assertNotNull(type.getKindForMimetype(Relation.CONTENT_ITEM_TYPE));
120 }
121
122 /**
123 * Initialize with "contacts_fallback.xml" and compare the DataKinds to those of
124 * {@link com.android.contacts.common.model.account.FallbackAccountType}.
125 */
126 public void testEditSchema_fallback() {
Jay Shrauner05452582015-08-29 11:34:25 -0700127 final ExternalAccountType type = new ExternalAccountType(getInstrumentation().getTargetContext(),
Jay Shrauner7bae0632015-08-27 16:23:44 -0700128 getInstrumentation().getContext().getPackageName(), false,
129 getInstrumentation().getContext().getResources().getXml(R.xml.contacts_fallback)
Chiao Chenge88fcd32012-11-13 18:38:05 -0800130 );
131
132 assertTrue(type.isInitialized());
133
134 // Create a fallback type with the same resource package name, and compare all the data
135 // kinds to its.
136 final AccountType reference = FallbackAccountType.createWithPackageNameForTest(
Jay Shrauner05452582015-08-29 11:34:25 -0700137 getInstrumentation().getTargetContext(), type.resourcePackageName);
Chiao Chenge88fcd32012-11-13 18:38:05 -0800138
139 assertsDataKindEquals(reference.getSortedDataKinds(), type.getSortedDataKinds());
140 }
141
142 public void testEditSchema_mustHaveChecks() {
143 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_base, true);
144 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_photo, false);
145 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name, false);
Chiao Chenge88fcd32012-11-13 18:38:05 -0800146 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr2, false);
147 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr3, false);
148 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr4, false);
149 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr5, false);
150 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr6, false);
151 checkEditSchema_mustHaveChecks(R.xml.missing_contacts_name_attr7, false);
152 }
153
154 private void checkEditSchema_mustHaveChecks(int xmlResId, boolean expectInitialized) {
Jay Shrauner05452582015-08-29 11:34:25 -0700155 final ExternalAccountType type = new ExternalAccountType(getInstrumentation().getTargetContext(),
Jay Shrauner7bae0632015-08-27 16:23:44 -0700156 getInstrumentation().getContext().getPackageName(), false,
157 getInstrumentation().getContext().getResources().getXml(xmlResId)
Chiao Chenge88fcd32012-11-13 18:38:05 -0800158 );
159
160 assertEquals(expectInitialized, type.isInitialized());
161 }
162
163 /**
164 * Initialize with "contacts_readonly.xml" and see if all data kinds are correctly registered.
165 */
166 public void testReadOnlyDefinition() {
Jay Shrauner05452582015-08-29 11:34:25 -0700167 final ExternalAccountType type = new ExternalAccountType(getInstrumentation().getTargetContext(),
Jay Shrauner7bae0632015-08-27 16:23:44 -0700168 getInstrumentation().getContext().getPackageName(), false,
169 getInstrumentation().getContext().getResources().getXml(R.xml.contacts_readonly)
Chiao Chenge88fcd32012-11-13 18:38:05 -0800170 );
171 assertTrue(type.isInitialized());
172
173 // Shouldn't have a "null" mimetype.
174 assertTrue(type.getKindForMimetype(null) == null);
175
Gary Mai7a6daea2016-10-10 15:41:48 -0700176 // 3 kinds are defined in XML and the rest are added by default.
177 assertEquals(3 + mDefaultMimetypes.size(), type.getSortedDataKinds().size());
Chiao Chenge88fcd32012-11-13 18:38:05 -0800178
179 // Check for the default kinds.
Gary Mai7a6daea2016-10-10 15:41:48 -0700180 for (String mimetype : mDefaultMimetypes) {
181 assertNotNull(type.getKindForMimetype(mimetype));
182 }
Chiao Chenge88fcd32012-11-13 18:38:05 -0800183
184 // Check for type specific kinds.
185 DataKind kind = type.getKindForMimetype("vnd.android.cursor.item/a.b.c");
186 assertNotNull(kind);
187 // No check for icon -- we actually just ignore it.
188 assertEquals("data1", ((BaseAccountType.SimpleInflater) kind.actionHeader)
189 .getColumnNameForTest());
190 assertEquals("data2", ((BaseAccountType.SimpleInflater) kind.actionBody)
191 .getColumnNameForTest());
Chiao Chenge88fcd32012-11-13 18:38:05 -0800192
193 kind = type.getKindForMimetype("vnd.android.cursor.item/d.e.f");
194 assertNotNull(kind);
195 assertEquals("data3", ((BaseAccountType.SimpleInflater) kind.actionHeader)
196 .getColumnNameForTest());
197 assertEquals("data4", ((BaseAccountType.SimpleInflater) kind.actionBody)
198 .getColumnNameForTest());
Chiao Chenge88fcd32012-11-13 18:38:05 -0800199
200 kind = type.getKindForMimetype("vnd.android.cursor.item/xyz");
201 assertNotNull(kind);
202 assertEquals("data5", ((BaseAccountType.SimpleInflater) kind.actionHeader)
203 .getColumnNameForTest());
204 assertEquals("data6", ((BaseAccountType.SimpleInflater) kind.actionBody)
205 .getColumnNameForTest());
Chiao Chenge88fcd32012-11-13 18:38:05 -0800206 }
207
208 private static void assertsDataKindEquals(List<DataKind> expectedKinds,
209 List<DataKind> actualKinds) {
210 final int count = Math.max(actualKinds.size(), expectedKinds.size());
211 for (int i = 0; i < count; i++) {
212 String actual = actualKinds.size() > i ? actualKinds.get(i).toString() : "(n/a)";
213 String expected = expectedKinds.size() > i ? expectedKinds.get(i).toString() : "(n/a)";
214
215 // Because assertEquals()'s output is not very friendly when comparing two similar
216 // strings, we manually do the check.
217 if (!Objects.equal(actual, expected)) {
218 final int commonPrefixEnd = findCommonPrefixEnd(actual, expected);
219 fail("Kind #" + i
220 + "\n[Actual]\n" + insertMarkerAt(actual, commonPrefixEnd)
221 + "\n[Expected]\n" + insertMarkerAt(expected, commonPrefixEnd));
222 }
223 }
224 }
225
226 private static int findCommonPrefixEnd(String s1, String s2) {
227 int i = 0;
228 for (;;) {
229 final boolean s1End = (s1.length() <= i);
230 final boolean s2End = (s2.length() <= i);
231 if (s1End || s2End) {
232 return i;
233 }
234 if (s1.charAt(i) != s2.charAt(i)) {
235 return i;
236 }
237 i++;
238 }
239 }
240
241 private static String insertMarkerAt(String s, int position) {
242 final String MARKER = "***";
243 if (position > s.length()) {
244 return s + MARKER;
245 } else {
246 return new StringBuilder(s).insert(position, MARKER).toString();
247 }
248 }
249}