1673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa/*
2673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project
3673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa *
4673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
5673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * you may not use this file except in compliance with the License.
6673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * You may obtain a copy of the License at
7673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa *
8673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
9673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa *
10673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
11673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
12673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * See the License for the specific language governing permissions and
14673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa * limitations under the License.
15673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa */
161a44d5dcabc18cd5ef111f732ccff91683a1a093Neal Nguyenpackage android.pim.vcard;
17673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
18673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.content.ContentProviderOperation;
19673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.content.ContentProviderResult;
20673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.content.ContentValues;
21673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.net.Uri;
22673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.Data;
23673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.RawContacts;
24673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email;
25673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event;
26673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
27673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im;
28673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname;
29673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note;
30673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization;
31673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone;
32673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo;
33673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Relation;
34673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
35673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
36673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website;
37673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.test.mock.MockContentResolver;
38673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport android.text.TextUtils;
39673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
40673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport junit.framework.TestCase;
41673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
42673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.ArrayList;
43673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.Arrays;
44673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.Collection;
45673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.HashMap;
46673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.HashSet;
47673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.Map;
48673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.Set;
49673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.SortedMap;
50673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.TreeMap;
51673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawaimport java.util.Map.Entry;
52673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
53673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa/* package */ class ImportTestResolver extends MockContentResolver {
54673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    final ImportTestProvider mProvider;
55673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
56673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public ImportTestResolver(TestCase testCase) {
57673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        mProvider = new ImportTestProvider(testCase);
58673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
59673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
60673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    @Override
61673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public ContentProviderResult[] applyBatch(String authority,
62673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ArrayList<ContentProviderOperation> operations) {
63673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        equalsString(authority, RawContacts.CONTENT_URI.toString());
64673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        return mProvider.applyBatch(operations);
65673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
66673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
67673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public void addExpectedContentValues(ContentValues expectedContentValues) {
68673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        mProvider.addExpectedContentValues(expectedContentValues);
69673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
70673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
71673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public void verify() {
72673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        mProvider.verify();
73673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
74673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
75673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    private static boolean equalsString(String a, String b) {
76673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (a == null || a.length() == 0) {
77673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            return b == null || b.length() == 0;
78673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        } else {
79673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            return a.equals(b);
80673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
81673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
82673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa}
83673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
84673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa/* package */ class ImportTestProvider extends MockContentProvider {
85673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    private static final Set<String> sKnownMimeTypeSet =
86673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        new HashSet<String>(Arrays.asList(StructuredName.CONTENT_ITEM_TYPE,
87673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Nickname.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE,
88673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Email.CONTENT_ITEM_TYPE, StructuredPostal.CONTENT_ITEM_TYPE,
89673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Im.CONTENT_ITEM_TYPE, Organization.CONTENT_ITEM_TYPE,
90673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Event.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE,
91673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Note.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE,
92673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Relation.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE,
93673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                GroupMembership.CONTENT_ITEM_TYPE));
94673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
95673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    final Map<String, Collection<ContentValues>> mMimeTypeToExpectedContentValues;
96673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
97673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    private final TestCase mTestCase;
98673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
99673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public ImportTestProvider(TestCase testCase) {
100673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        mTestCase = testCase;
101673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        mMimeTypeToExpectedContentValues =
102673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            new HashMap<String, Collection<ContentValues>>();
103673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (String acceptanbleMimeType : sKnownMimeTypeSet) {
104673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            // Do not use HashSet since the current implementation changes the content of
105673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            // ContentValues after the insertion, which make the result of hashCode()
106673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            // changes...
107673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            mMimeTypeToExpectedContentValues.put(
108673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    acceptanbleMimeType, new ArrayList<ContentValues>());
109673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
110673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
111673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
112673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public void addExpectedContentValues(ContentValues expectedContentValues) {
113673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        final String mimeType = expectedContentValues.getAsString(Data.MIMETYPE);
114673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (!sKnownMimeTypeSet.contains(mimeType)) {
115673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            mTestCase.fail(String.format(
116673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    "Unknow MimeType %s in the test code. Test code should be broken.",
117673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    mimeType));
118673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
119673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
120673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        final Collection<ContentValues> contentValuesCollection =
121673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mMimeTypeToExpectedContentValues.get(mimeType);
122673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        contentValuesCollection.add(expectedContentValues);
123673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
124673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
125673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    @Override
126673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public ContentProviderResult[] applyBatch(
127673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ArrayList<ContentProviderOperation> operations) {
128673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (operations == null) {
129673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            mTestCase.fail("There is no operation.");
130673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
131673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
132673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        final int size = operations.size();
133673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        ContentProviderResult[] fakeResultArray = new ContentProviderResult[size];
134673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (int i = 0; i < size; i++) {
135673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            Uri uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, String.valueOf(i));
136673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            fakeResultArray[i] = new ContentProviderResult(uri);
137673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
138673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
139673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (int i = 0; i < size; i++) {
140673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ContentProviderOperation operation = operations.get(i);
141673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ContentValues contentValues = operation.resolveValueBackReferences(
142673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    fakeResultArray, i);
143673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
144673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (int i = 0; i < size; i++) {
145673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ContentProviderOperation operation = operations.get(i);
146673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ContentValues actualContentValues = operation.resolveValueBackReferences(
147673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    fakeResultArray, i);
148673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final Uri uri = operation.getUri();
149673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            if (uri.equals(RawContacts.CONTENT_URI)) {
150673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mTestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_NAME));
151673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mTestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_TYPE));
152673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            } else if (uri.equals(Data.CONTENT_URI)) {
153673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                final String mimeType = actualContentValues.getAsString(Data.MIMETYPE);
154673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                if (!sKnownMimeTypeSet.contains(mimeType)) {
155673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    mTestCase.fail(String.format(
156673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            "Unknown MimeType %s. Probably added after developing this test",
157673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            mimeType));
158673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
159673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // Remove data meaningless in this unit tests.
160673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // Specifically, Data.DATA1 - DATA7 are set to null or empty String
161673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // regardless of the input, but it may change depending on how
162673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // resolver-related code handles it.
163673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // Here, we ignore these implementation-dependent specs and
164673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // just check whether vCard importer correctly inserts rellevent data.
165673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Set<String> keyToBeRemoved = new HashSet<String>();
166673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                for (Entry<String, Object> entry : actualContentValues.valueSet()) {
167673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    Object value = entry.getValue();
168673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    if (value == null || TextUtils.isEmpty(value.toString())) {
169673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        keyToBeRemoved.add(entry.getKey());
170673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    }
171673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
172673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                for (String key: keyToBeRemoved) {
173673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    actualContentValues.remove(key);
174673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
175673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                /* for testing
176673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Log.d("@@@",
177673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        String.format("MimeType: %s, data: %s",
178673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                                mimeType, actualContentValues.toString())); */
179673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // Remove RAW_CONTACT_ID entry just for safety, since we do not care
180673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                // how resolver-related code handles the entry in this unit test,
181673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                if (actualContentValues.containsKey(Data.RAW_CONTACT_ID)) {
182673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    actualContentValues.remove(Data.RAW_CONTACT_ID);
183673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
184673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                final Collection<ContentValues> contentValuesCollection =
185673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    mMimeTypeToExpectedContentValues.get(mimeType);
186673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                if (contentValuesCollection.isEmpty()) {
187673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    mTestCase.fail("ContentValues for MimeType " + mimeType
188673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            + " is not expected at all (" + actualContentValues + ")");
189673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
190673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                boolean checked = false;
191673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                for (ContentValues expectedContentValues : contentValuesCollection) {
192673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    /*for testing
193673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    Log.d("@@@", "expected: "
194673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            + convertToEasilyReadableString(expectedContentValues));
195673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    Log.d("@@@", "actual  : "
196673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            + convertToEasilyReadableString(actualContentValues));*/
197673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    if (equalsForContentValues(expectedContentValues,
198673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                            actualContentValues)) {
199673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        mTestCase.assertTrue(contentValuesCollection.remove(expectedContentValues));
200673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        checked = true;
201673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        break;
202673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    }
203673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
204673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                if (!checked) {
205673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    final StringBuilder builder = new StringBuilder();
206673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    builder.append("Unexpected: ");
207673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    builder.append(convertToEasilyReadableString(actualContentValues));
208673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    builder.append("\nExpected: ");
209673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    for (ContentValues expectedContentValues : contentValuesCollection) {
210673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                        builder.append(convertToEasilyReadableString(expectedContentValues));
211673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    }
212673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    mTestCase.fail(builder.toString());
213673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
214673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            } else {
215673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mTestCase.fail("Unexpected Uri has come: " + uri);
216673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            }
217673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }  // for (int i = 0; i < size; i++) {
2187e25f5cbfbe433c6ffe06a17ef42c471baf07c93Daniel Lehmann        return fakeResultArray;
219673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
220673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
221673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    public void verify() {
222673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
223673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (Collection<ContentValues> contentValuesCollection :
224673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mMimeTypeToExpectedContentValues.values()) {
225673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            for (ContentValues expectedContentValues: contentValuesCollection) {
226673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                builder.append(convertToEasilyReadableString(expectedContentValues));
227673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                builder.append("\n");
228673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            }
229673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
230673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (builder.length() > 0) {
231673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String failMsg =
232673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                "There is(are) remaining expected ContentValues instance(s): \n"
233673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    + builder.toString();
234673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            mTestCase.fail(failMsg);
235673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
236673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
237673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
238673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    /**
239673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa     * Utility method to print ContentValues whose content is printed with sorted keys.
240673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa     */
241673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    private String convertToEasilyReadableString(ContentValues contentValues) {
242673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (contentValues == null) {
243673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            return "null";
244673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
245673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        String mimeTypeValue = "";
246673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        SortedMap<String, String> sortedMap = new TreeMap<String, String>();
247673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (Entry<String, Object> entry : contentValues.valueSet()) {
248673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String key = entry.getKey();
249673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final Object value = entry.getValue();
250673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String valueString = (value != null ? value.toString() : null);
251673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            if (Data.MIMETYPE.equals(key)) {
252673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mimeTypeValue = valueString;
253673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            } else {
254673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                mTestCase.assertNotNull(key);
255673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                sortedMap.put(key, valueString);
256673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            }
257673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
258673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
259673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        builder.append(Data.MIMETYPE);
260673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        builder.append('=');
261673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        builder.append(mimeTypeValue);
262673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (Entry<String, String> entry : sortedMap.entrySet()) {
263673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String key = entry.getKey();
264673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String value = entry.getValue();
265673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            builder.append(' ');
266673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            builder.append(key);
267673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            builder.append("=\"");
268673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            builder.append(value);
269673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            builder.append('"');
270673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
271673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        return builder.toString();
272673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
273673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
274673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    private static boolean equalsForContentValues(
275673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            ContentValues expected, ContentValues actual) {
276673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        if (expected == actual) {
277673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            return true;
278673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        } else if (expected == null || actual == null || expected.size() != actual.size()) {
279673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            return false;
280673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
281673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa
282673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        for (Entry<String, Object> entry : expected.valueSet()) {
283673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final String key = entry.getKey();
284673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            final Object value = entry.getValue();
285673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            if (!actual.containsKey(key)) {
286673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                return false;
287673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            }
288673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            if (value instanceof byte[]) {
289673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                Object actualValue = actual.get(key);
290673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                if (!Arrays.equals((byte[])value, (byte[])actualValue)) {
291673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    return false;
292673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                }
293673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            } else if (!value.equals(actual.get(key))) {
294673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa                    return false;
295673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa            }
296673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        }
297673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa        return true;
298673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa    }
299673c1d1fc9f3c004e999f763a9c718e656497d32Daisuke Miyakawa}
300