14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/*
24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project
34199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
44199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not
54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * use this file except in compliance with the License. You may obtain a copy of
64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License at
74199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
84199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0
94199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * License for the specific language governing permissions and limitations under
144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * the License.
154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
16677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawapackage com.android.vcard.tests.testutils;
174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
187e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.content.ContentResolver;
197e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.content.EntityIterator;
207e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.database.Cursor;
217e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.net.Uri;
227e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.test.AndroidTestCase;
237e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.test.mock.MockContext;
247e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.text.TextUtils;
257e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawaimport android.util.Log;
267e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa
272c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.VCardComposer;
282c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.VCardConfig;
292c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.VCardEntryConstructor;
302c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.VCardParser;
312c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.VCardUtils;
322c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Chengimport com.android.vcard.exception.VCardException;
332c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng
34a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawaimport junit.framework.TestCase;
35a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.ByteArrayInputStream;
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.IOException;
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.InputStream;
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.lang.reflect.Method;
404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class lets users checks that given expected vCard data are same as given actual vCard data.
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Able to verify both vCard importer/exporter.
454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * First a user has to initialize the object by calling either
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link #initForImportTest(int, int)} or {@link #initForExportTest(int)}.
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * "Round trip test" (import -> export -> import, or export -> import -> export) is not supported.
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardVerifier {
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private static final String LOG_TAG = "VCardVerifier";
5456174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa    private static final boolean DEBUG = true;
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
567e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa    /**
577e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa     * Special URI for testing.
587e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa     */
597e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa    /* package */ static final String VCARD_TEST_AUTHORITY = "com.android.unit_tests.vcard";
607e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa    private static final Uri VCARD_TEST_AUTHORITY_URI =
617e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa            Uri.parse("content://" + VCARD_TEST_AUTHORITY);
627e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa    /* package */ static final Uri CONTACTS_TEST_CONTENT_URI =
63677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa            Uri.withAppendedPath(VCARD_TEST_AUTHORITY_URI, "contacts");
647e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private static class CustomMockContext extends MockContext {
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final ContentResolver mResolver;
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public CustomMockContext(ContentResolver resolver) {
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mResolver = resolver;
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public ContentResolver getContentResolver() {
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return mResolver;
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
77a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    private final AndroidTestCase mAndroidTestCase;
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private int mVCardType;
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private boolean mIsDoCoMo;
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // Only one of them must be non-empty.
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private ExportTestResolver mExportTestResolver;
834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private InputStream mInputStream;
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // To allow duplication, use list instead of set.
864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // When null, we don't need to do the verification.
874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private PropertyNodesVerifier mPropertyNodesVerifier;
884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private LineVerifier mLineVerifier;
894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private ContentValuesVerifier mContentValuesVerifier;
904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private boolean mInitialized;
914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private boolean mVerified = false;
924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mCharset;
934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
942c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng    private String mExceptionContents;
952c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng
964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // Called by VCardTestsBase
97a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    public VCardVerifier(AndroidTestCase androidTestCase) {
98a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        mAndroidTestCase = androidTestCase;
994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mExportTestResolver = null;
1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mInputStream = null;
1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mInitialized = false;
1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVerified = false;
1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // Should be called at the beginning of each import test.
1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void initForImportTest(int vcardType, int resId) {
1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mInitialized) {
108be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Already initialized");
1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVCardType = vcardType;
1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        setInputResourceId(resId);
1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mInitialized = true;
1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    // Should be called at the beginning of each export test.
1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void initForExportTest(int vcardType) {
1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        initForExportTest(vcardType, "UTF-8");
1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void initForExportTest(int vcardType, String charset) {
1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mInitialized) {
123be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Already initialized");
1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
125a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        mExportTestResolver = new ExportTestResolver(mAndroidTestCase);
1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVCardType = vcardType;
1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mInitialized = true;
1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (TextUtils.isEmpty(charset)) {
1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCharset = "UTF-8";
1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCharset = charset;
1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void setInputResourceId(int resId) {
137677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa        final InputStream inputStream =
138677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa                mAndroidTestCase.getContext().getResources().openRawResource(resId);
1394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (inputStream == null) {
140be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Wrong resId: " + resId);
1414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        setInputStream(inputStream);
1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void setInputStream(InputStream inputStream) {
1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mExportTestResolver != null) {
147be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("addInputEntry() is called.");
1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mInputStream != null) {
149be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("InputStream is already set");
1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mInputStream = inputStream;
1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public ContactEntry addInputEntry() {
1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
156be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not initialized");
1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mInputStream != null) {
159be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("setInputStream is called");
1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mExportTestResolver.addInputContactEntry();
1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
164a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    public PropertyNodesVerifierElem addPropertyNodesVerifierElemWithoutVersion() {
1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
166be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not initialized");
1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPropertyNodesVerifier == null) {
169a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            mPropertyNodesVerifier = new PropertyNodesVerifier(mAndroidTestCase);
1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
171a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        return mPropertyNodesVerifier.addPropertyNodesVerifierElem();
172a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    }
173677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa
174a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    public PropertyNodesVerifierElem addPropertyNodesVerifierElem() {
175a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        final PropertyNodesVerifierElem elem = addPropertyNodesVerifierElemWithoutVersion();
176be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        final String versionString;
177be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        if (VCardConfig.isVersion21(mVCardType)) {
178be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            versionString = "2.1";
179be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        } else if (VCardConfig.isVersion30(mVCardType)) {
180be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            versionString = "3.0";
181be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        } else if (VCardConfig.isVersion40(mVCardType)) {
182be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            versionString = "4.0";
183be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        } else {
184be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            throw new RuntimeException("Unexpected vcard type during a unit test");
185be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        }
186be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        elem.addExpectedNodeWithOrder("VERSION", versionString);
1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return elem;
1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public PropertyNodesVerifierElem addPropertyNodesVerifierElemWithEmptyName() {
1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
193be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not initialized");
1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1953d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa        final PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem();
1963d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa        if (VCardConfig.isVersion40(mVCardType)) {
1973d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa            elem.addExpectedNodeWithOrder("FN", "");
1983d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa        } else if (VCardConfig.isVersion30(mVCardType)) {
1993d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa            elem.addExpectedNodeWithOrder("N", "");
2003d77102a83d0e412046ca0ff9dfdef1a44050ca3Daisuke Miyakawa            elem.addExpectedNodeWithOrder("FN", "");
2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mIsDoCoMo) {
2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            elem.addExpectedNodeWithOrder("N", "");
2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return elem;
2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public LineVerifierElem addLineVerifierElem() {
2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
209be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not initialized");
2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mLineVerifier == null) {
212a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            mLineVerifier = new LineVerifier(mAndroidTestCase, mVCardType);
2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mLineVerifier.addLineVerifierElem();
2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public ContentValuesVerifierElem addContentValuesVerifierElem() {
2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
219be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not initialized");
2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mContentValuesVerifier == null) {
2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mContentValuesVerifier = new ContentValuesVerifier();
2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
225a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        return mContentValuesVerifier.addElem(mAndroidTestCase);
2264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2282c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng    public void addVCardExceptionVerifier(String contents) {
2292c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng        mExceptionContents = contents;
2302c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng    }
2312c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng
232a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    /**
233677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa     * Sets up sub-verifiers correctly and tries to parse vCard as {@link InputStream}.
234a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa     * Errors around InputStream must be handled outside this method.
235a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa     *
236a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa     * Used both from {@link #verifyForImportTest()} and from {@link #verifyForExportTest()}.
237a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa     */
238a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    private void verifyWithInputStream(InputStream is) throws IOException {
2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        try {
2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Note: we must not specify charset toward vCard parsers. This code checks whether
2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // those parsers are able to encode given binary without any extra information for
2424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // charset.
243be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            final VCardParser parser = VCardUtils.getAppropriateParser(mVCardType);
2449ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa            if (mContentValuesVerifier != null) {
2459ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa                final VCardEntryConstructor constructor = new VCardEntryConstructor(mVCardType);
2469ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa                constructor.addEntryHandler(mContentValuesVerifier);
2479ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa                parser.addInterpreter(constructor);
2489ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa            }
2499ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa            if (mPropertyNodesVerifier != null) {
2509ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa                parser.addInterpreter(mPropertyNodesVerifier);
2519ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa            }
2529ec6c05a1dbb17862a44f96e91975dfc01cebf6eDaisuke Miyakawa            parser.parse(is);
2532c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng            if (mExceptionContents != null) {
2542c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng                // exception contents exists, we expect an exception to occur.
2552c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng                AndroidTestCase.fail();
2562c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng            }
257a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        } catch (VCardException e) {
2582c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng            if (mExceptionContents != null) {
2592c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng                AndroidTestCase.assertTrue(e.getMessage().contains(mExceptionContents));
2602c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng            } else {
2612c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng                Log.e(LOG_TAG, "VCardException", e);
2622c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng                AndroidTestCase.fail("Unexpected VCardException: " + e.getMessage());
2632c9cf383b1c956c7185e97c2417ebd85b48fc0acChiao Cheng            }
264a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        }
265a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    }
266a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa
267a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    private void verifyOneVCardForExport(final String vcard) {
268677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawa        if (DEBUG) Log.d(LOG_TAG, vcard);
269a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        InputStream is = null;
270a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        try {
2714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            is = new ByteArrayInputStream(vcard.getBytes(mCharset));
272a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            verifyWithInputStream(is);
2734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } catch (IOException e) {
274be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Unexpected IOException: " + e.getMessage());
2754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } finally {
2764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (is != null) {
2774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                try {
2784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    is.close();
2794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } catch (IOException e) {
280be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa                    AndroidTestCase.fail("Unexpected IOException: " + e.getMessage());
2814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
2824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
2834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void verify() {
2874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!mInitialized) {
288a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            TestCase.fail("Not initialized.");
2894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mVerified) {
291a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            TestCase.fail("verify() was called twice.");
2924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
293a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa
2944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mInputStream != null) {
295a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            if (mExportTestResolver != null){
296a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa                TestCase.fail("There are two input sources.");
2974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
298a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            verifyForImportTest();
2994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mExportTestResolver != null){
3004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            verifyForExportTest();
3014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
302a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            TestCase.fail("No input is determined");
3034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVerified = true;
3054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
307a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa    private void verifyForImportTest() {
3084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mLineVerifier != null) {
309be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("Not supported now.");
3104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
311a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa
312a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        try {
313a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            verifyWithInputStream(mInputStream);
314a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        } catch (IOException e) {
315a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            AndroidTestCase.fail("IOException was thrown: " + e.getMessage());
316a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa        } finally {
317a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            if (mInputStream != null) {
318a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa                try {
319a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa                    mInputStream.close();
320a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa                } catch (IOException e) {
321a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa                }
322a76f41e328f31c2e9e9006160d8f65fe651eeb6aDaisuke Miyakawa            }
3234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public static EntityIterator mockGetEntityIteratorMethod(
3274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final ContentResolver resolver,
3284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Uri uri, final String selection,
3294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String[] selectionArgs, final String sortOrder) {
3304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (ExportTestResolver.class.equals(resolver.getClass())) {
3314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return ((ExportTestResolver)resolver).getProvider().queryEntities(
3324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    uri, selection, selectionArgs, sortOrder);
3334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        Log.e(LOG_TAG, "Unexpected provider given.");
3364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return null;
3374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private Method getMockGetEntityIteratorMethod()
3404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            throws SecurityException, NoSuchMethodException {
3414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return this.getClass().getMethod("mockGetEntityIteratorMethod",
3424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                ContentResolver.class, Uri.class, String.class, String[].class, String.class);
3434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void verifyForExportTest() {
3467e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        final CustomMockContext context = new CustomMockContext(mExportTestResolver);
3477e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        final ContentResolver resolver = context.getContentResolver();
3487e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        final VCardComposer composer = new VCardComposer(context, mVCardType, mCharset);
3497e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        // projection is ignored.
3507e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        final Cursor cursor = resolver.query(CONTACTS_TEST_CONTENT_URI, null, null, null, null);
3517e4e86eb5ad2c8a68ca7005ef4dee64a82ce0198Daisuke Miyakawa        if (!composer.init(cursor)) {
352be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa            AndroidTestCase.fail("init() failed. Reason: " + composer.getErrorReason());
3534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
354be378d5b188f51cf717e5309e3c39180e85833a8Daisuke Miyakawa        AndroidTestCase.assertFalse(composer.isAfterLast());
3554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        try {
3564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            while (!composer.isAfterLast()) {
35756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                Method mockGetEntityIteratorMethod = null;
3584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                try {
35956174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                    mockGetEntityIteratorMethod = getMockGetEntityIteratorMethod();
3604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } catch (Exception e) {
36156174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                    AndroidTestCase.fail("Exception thrown: " + e);
3624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
36356174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                AndroidTestCase.assertNotNull(mockGetEntityIteratorMethod);
36456174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                final String vcard = composer.createOneEntry(mockGetEntityIteratorMethod);
36556174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                AndroidTestCase.assertNotNull(vcard);
36656174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                if (mLineVerifier != null) {
36756174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                    mLineVerifier.verify(vcard);
36856174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                }
36956174dfd0654acbe828e4db38537ec5a3a04d466Daisuke Miyakawa                verifyOneVCardForExport(vcard);
3704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
3714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } finally {
3724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            composer.terminate();
3734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
376