1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.pim.vcard; 17 18import android.content.ContentProvider; 19import android.content.ContentResolver; 20import android.content.Context; 21import android.content.EntityIterator; 22import android.net.Uri; 23import android.pim.vcard.VCardComposer; 24import android.pim.vcard.VCardConfig; 25import android.pim.vcard.VCardEntryConstructor; 26import android.pim.vcard.VCardInterpreter; 27import android.pim.vcard.VCardInterpreterCollection; 28import android.pim.vcard.VCardParser; 29import android.pim.vcard.VCardParser_V21; 30import android.pim.vcard.VCardParser_V30; 31import android.pim.vcard.exception.VCardException; 32import android.test.AndroidTestCase; 33import android.test.mock.MockContext; 34 35import java.io.ByteArrayInputStream; 36import java.io.IOException; 37import java.io.InputStream; 38import java.lang.reflect.Method; 39import java.util.Arrays; 40 41/* package */ class CustomMockContext extends MockContext { 42 final ContentResolver mResolver; 43 public CustomMockContext(ContentResolver resolver) { 44 mResolver = resolver; 45 } 46 47 @Override 48 public ContentResolver getContentResolver() { 49 return mResolver; 50 } 51} 52 53/* package */ class VCardVerifier { 54 private class VCardVerifierInternal implements VCardComposer.OneEntryHandler { 55 public boolean onInit(Context context) { 56 return true; 57 } 58 public boolean onEntryCreated(String vcard) { 59 verifyOneVCard(vcard); 60 return true; 61 } 62 public void onTerminate() { 63 } 64 } 65 66 private final AndroidTestCase mTestCase; 67 private final VCardVerifierInternal mVCardVerifierInternal; 68 private int mVCardType; 69 private boolean mIsV30; 70 private boolean mIsDoCoMo; 71 72 // Only one of them must be non-empty. 73 private ExportTestResolver mExportTestResolver; 74 private InputStream mInputStream; 75 76 // To allow duplication, use list instead of set. 77 // When null, we don't need to do the verification. 78 private PropertyNodesVerifier mPropertyNodesVerifier; 79 private LineVerifier mLineVerifier; 80 private ContentValuesVerifier mContentValuesVerifier; 81 private boolean mInitialized; 82 private boolean mVerified = false; 83 84 public VCardVerifier(AndroidTestCase androidTestCase) { 85 mTestCase = androidTestCase; 86 mVCardVerifierInternal = new VCardVerifierInternal(); 87 mExportTestResolver = null; 88 mInputStream = null; 89 mInitialized = false; 90 mVerified = false; 91 } 92 93 public void initForExportTest(int vcardType) { 94 if (mInitialized) { 95 mTestCase.fail("Already initialized"); 96 } 97 mExportTestResolver = new ExportTestResolver(mTestCase); 98 mVCardType = vcardType; 99 mIsV30 = VCardConfig.isV30(vcardType); 100 mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 101 mInitialized = true; 102 } 103 104 public void initForImportTest(int vcardType, int resId) { 105 if (mInitialized) { 106 mTestCase.fail("Already initialized"); 107 } 108 mVCardType = vcardType; 109 mIsV30 = VCardConfig.isV30(vcardType); 110 mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); 111 setInputResourceId(resId); 112 mInitialized = true; 113 } 114 115 private void setInputResourceId(int resId) { 116 InputStream inputStream = mTestCase.getContext().getResources().openRawResource(resId); 117 if (inputStream == null) { 118 mTestCase.fail("Wrong resId: " + resId); 119 } 120 setInputStream(inputStream); 121 } 122 123 private void setInputStream(InputStream inputStream) { 124 if (mExportTestResolver != null) { 125 mTestCase.fail("addInputEntry() is called."); 126 } else if (mInputStream != null) { 127 mTestCase.fail("InputStream is already set"); 128 } 129 mInputStream = inputStream; 130 } 131 132 public ContactEntry addInputEntry() { 133 if (!mInitialized) { 134 mTestCase.fail("Not initialized"); 135 } 136 if (mInputStream != null) { 137 mTestCase.fail("setInputStream is called"); 138 } 139 return mExportTestResolver.addInputContactEntry(); 140 } 141 142 public PropertyNodesVerifierElem addPropertyNodesVerifierElem() { 143 if (!mInitialized) { 144 mTestCase.fail("Not initialized"); 145 } 146 if (mPropertyNodesVerifier == null) { 147 mPropertyNodesVerifier = new PropertyNodesVerifier(mTestCase); 148 } 149 PropertyNodesVerifierElem elem = 150 mPropertyNodesVerifier.addPropertyNodesVerifierElem(); 151 elem.addExpectedNodeWithOrder("VERSION", (mIsV30 ? "3.0" : "2.1")); 152 153 return elem; 154 } 155 156 public PropertyNodesVerifierElem addPropertyNodesVerifierElemWithEmptyName() { 157 if (!mInitialized) { 158 mTestCase.fail("Not initialized"); 159 } 160 PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem(); 161 if (mIsV30) { 162 elem.addExpectedNodeWithOrder("N", "").addExpectedNodeWithOrder("FN", ""); 163 } else if (mIsDoCoMo) { 164 elem.addExpectedNodeWithOrder("N", ""); 165 } 166 return elem; 167 } 168 169 public LineVerifierElem addLineVerifierElem() { 170 if (!mInitialized) { 171 mTestCase.fail("Not initialized"); 172 } 173 if (mLineVerifier == null) { 174 mLineVerifier = new LineVerifier(mTestCase, mVCardType); 175 } 176 return mLineVerifier.addLineVerifierElem(); 177 } 178 179 public ContentValuesVerifierElem addContentValuesVerifierElem() { 180 if (!mInitialized) { 181 mTestCase.fail("Not initialized"); 182 } 183 if (mContentValuesVerifier == null) { 184 mContentValuesVerifier = new ContentValuesVerifier(); 185 } 186 187 return mContentValuesVerifier.addElem(mTestCase); 188 } 189 190 private void verifyOneVCard(final String vcard) { 191 // Log.d("@@@", vcard); 192 final VCardInterpreter builder; 193 if (mContentValuesVerifier != null) { 194 final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier; 195 final VCardEntryConstructor vcardDataBuilder = 196 new VCardEntryConstructor(mVCardType); 197 vcardDataBuilder.addEntryHandler(mContentValuesVerifier); 198 if (mPropertyNodesVerifier != null) { 199 builder = new VCardInterpreterCollection(Arrays.asList( 200 mPropertyNodesVerifier, vcardDataBuilder)); 201 } else { 202 builder = vnodeBuilder; 203 } 204 } else { 205 if (mPropertyNodesVerifier != null) { 206 builder = mPropertyNodesVerifier; 207 } else { 208 return; 209 } 210 } 211 212 final VCardParser parser = 213 (mIsV30 ? new VCardParser_V30(true) : new VCardParser_V21()); 214 InputStream is = null; 215 try { 216 String charset = 217 (VCardConfig.usesShiftJis(mVCardType) ? "SHIFT_JIS" : "UTF-8"); 218 is = new ByteArrayInputStream(vcard.getBytes(charset)); 219 mTestCase.assertEquals(true, parser.parse(is, null, builder)); 220 } catch (IOException e) { 221 mTestCase.fail("Unexpected IOException: " + e.getMessage()); 222 } catch (VCardException e) { 223 mTestCase.fail("Unexpected VCardException: " + e.getMessage()); 224 } finally { 225 if (is != null) { 226 try { 227 is.close(); 228 } catch (IOException e) { 229 } 230 } 231 } 232 } 233 234 public void verify() { 235 if (!mInitialized) { 236 mTestCase.fail("Not initialized."); 237 } 238 if (mVerified) { 239 mTestCase.fail("verify() was called twice."); 240 } 241 if (mInputStream != null) { 242 try { 243 verifyForImportTest(); 244 } catch (IOException e) { 245 mTestCase.fail("IOException was thrown: " + e.getMessage()); 246 } catch (VCardException e) { 247 mTestCase.fail("VCardException was thrown: " + e.getMessage()); 248 } 249 } else if (mExportTestResolver != null){ 250 verifyForExportTest(); 251 } else { 252 mTestCase.fail("No input is determined"); 253 } 254 mVerified = true; 255 } 256 257 private void verifyForImportTest() throws IOException, VCardException { 258 if (mLineVerifier != null) { 259 mTestCase.fail("Not supported now."); 260 } 261 if (mContentValuesVerifier != null) { 262 mContentValuesVerifier.verify(mInputStream, mVCardType); 263 } 264 } 265 266 public static EntityIterator mockGetEntityIteratorMethod( 267 final ContentResolver resolver, 268 final Uri uri, final String selection, 269 final String[] selectionArgs, final String sortOrder) { 270 final ContentProvider provider = 271 resolver.acquireContentProviderClient(uri).getLocalContentProvider(); 272 return ((ExportTestProvider)provider).queryEntities( 273 uri, selection, selectionArgs, sortOrder); 274 } 275 276 private Method getMockGetEntityIteratorMethod() 277 throws SecurityException, NoSuchMethodException { 278 return this.getClass().getMethod("mockGetEntityIteratorMethod", 279 ContentResolver.class, Uri.class, String.class, String[].class, String.class); 280 } 281 282 private void verifyForExportTest() { 283 final VCardComposer composer = 284 new VCardComposer(new CustomMockContext(mExportTestResolver), mVCardType); 285 composer.addHandler(mLineVerifier); 286 composer.addHandler(mVCardVerifierInternal); 287 if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) { 288 mTestCase.fail("init() failed. Reason: " + composer.getErrorReason()); 289 } 290 mTestCase.assertFalse(composer.isAfterLast()); 291 try { 292 while (!composer.isAfterLast()) { 293 try { 294 final Method mockGetEntityIteratorMethod = getMockGetEntityIteratorMethod(); 295 mTestCase.assertTrue( 296 composer.createOneEntry(getMockGetEntityIteratorMethod())); 297 } catch (Exception e) { 298 e.printStackTrace(); 299 mTestCase.fail(); 300 } 301 } 302 } finally { 303 composer.terminate(); 304 } 305 } 306} 307