1b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook/* 2b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Copyright (C) 2010 The Android Open Source Project 3b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 4b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License"); 5b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * you may not use this file except in compliance with the License. 6b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * You may obtain a copy of the License at 7b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 8b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * http://www.apache.org/licenses/LICENSE-2.0 9b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 10b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Unless required by applicable law or agreed to in writing, software 11b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS, 12b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * See the License for the specific language governing permissions and 14b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * limitations under the License. 15b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook */ 16b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 17b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookpackage com.android.exchange.adapter; 18b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 19b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.exchange.adapter.AbstractSyncAdapter.Operation; 20b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.exchange.adapter.CalendarSyncAdapter.CalendarOperations; 21b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.exchange.adapter.CalendarSyncAdapter.EasCalendarSyncParser; 22b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.exchange.provider.MockProvider; 23b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 24b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.ContentProviderOperation; 25b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.ContentValues; 26b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.Context; 27b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.OperationApplicationException; 28b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.res.Resources; 29b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.database.Cursor; 30b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.os.RemoteException; 31b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.provider.CalendarContract.Attendees; 32b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.provider.CalendarContract.Events; 33b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.test.IsolatedContext; 34b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.test.RenamingDelegatingContext; 35b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.test.mock.MockContentResolver; 36b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.test.mock.MockContext; 37b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.test.suitebuilder.annotation.MediumTest; 38b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 39b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.io.ByteArrayInputStream; 40b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.io.File; 41b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.io.IOException; 42b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.util.ArrayList; 43b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.util.GregorianCalendar; 44b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.util.List; 45b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.util.TimeZone; 46b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 47b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook/** 48b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * You can run this entire test case with: 49b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * runtest -c com.android.exchange.adapter.CalendarSyncAdapterTests exchange 50b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook */ 51b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook@MediumTest 52b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookpublic class CalendarSyncAdapterTests extends SyncAdapterTestCase<CalendarSyncAdapter> { 53b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final String[] ATTENDEE_PROJECTION = new String[] {Attendees.ATTENDEE_EMAIL, 54b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Attendees.ATTENDEE_NAME, Attendees.ATTENDEE_STATUS}; 55b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final int ATTENDEE_EMAIL = 0; 56b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final int ATTENDEE_NAME = 1; 57b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final int ATTENDEE_STATUS = 2; 58b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 59b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final String SINGLE_ATTENDEE_EMAIL = "attendee@host.com"; 60b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final String SINGLE_ATTENDEE_NAME = "Bill Attendee"; 61b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 62b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private Context mMockContext; 63b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private MockContentResolver mMockResolver; 64b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 65b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // This is the US/Pacific time zone as a base64-encoded TIME_ZONE_INFORMATION structure, as 66b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // it would appear coming from an Exchange server 67b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private static final String TEST_TIME_ZONE = "4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByA" + 68b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook "GQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAFAAY" + 69b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook "QBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAAAAAAAAAAAAAAAAAAAA" + 70b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook "AAAAAAAAAMAAAACAAIAAAAAAAAAxP///w=="; 71b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 72b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private class MockContext2 extends MockContext { 73b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 74b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook @Override 75b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public Resources getResources() { 76b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return getContext().getResources(); 77b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 78b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 79b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook @Override 80b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public File getDir(String name, int mode) { 81b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // name the directory so the directory will be separated from 82b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // one created through the regular Context 83b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return getContext().getDir("mockcontext2_" + name, mode); 84b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 85b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 86b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook @Override 87b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public Context getApplicationContext() { 88b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return this; 89b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 90b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 91b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 92b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook @Override 93b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void setUp() throws Exception { 94b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook super.setUp(); 95b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 96b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mMockResolver = new MockContentResolver(); 97b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook final String filenamePrefix = "test."; 98b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook RenamingDelegatingContext targetContextWrapper = new 99b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook RenamingDelegatingContext( 100b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook new MockContext2(), // The context that most methods are delegated to 101b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook getContext(), // The context that file methods are delegated to 102b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook filenamePrefix); 103b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mMockContext = new IsolatedContext(mMockResolver, targetContextWrapper); 104b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mMockResolver.addProvider(MockProvider.AUTHORITY, new MockProvider(mMockContext)); 105b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 106b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 107b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public CalendarSyncAdapterTests() { 108b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook super(); 109b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 110b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 111b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testSetTimeRelatedValues_NonRecurring() throws IOException { 112b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 113b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = adapter.new EasCalendarSyncParser(getTestInputStream(), adapter); 114b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentValues cv = new ContentValues(); 115b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Basic, one-time meeting lasting an hour 116b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar startCalendar = new GregorianCalendar(2010, 5, 10, 8, 30); 117b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long startTime = startCalendar.getTimeInMillis(); 118b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar endCalendar = new GregorianCalendar(2010, 5, 10, 9, 30); 119b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long endTime = endCalendar.getTimeInMillis(); 120b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 121b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.setTimeRelatedValues(cv, startTime, endTime, 0); 122b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsInteger(Events.DURATION)); 123b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(startTime, cv.getAsLong(Events.DTSTART)); 124b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(endTime, cv.getAsLong(Events.DTEND)); 125b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(endTime, cv.getAsLong(Events.LAST_DATE)); 126b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsString(Events.EVENT_TIMEZONE)); 127b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 128b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 129b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testSetTimeRelatedValues_Recurring() throws IOException { 130b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 131b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = adapter.new EasCalendarSyncParser(getTestInputStream(), adapter); 132b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentValues cv = new ContentValues(); 133b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Recurring meeting lasting an hour 134b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar startCalendar = new GregorianCalendar(2010, 5, 10, 8, 30); 135b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long startTime = startCalendar.getTimeInMillis(); 136b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar endCalendar = new GregorianCalendar(2010, 5, 10, 9, 30); 137b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long endTime = endCalendar.getTimeInMillis(); 138b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.RRULE, "FREQ=DAILY"); 139b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.setTimeRelatedValues(cv, startTime, endTime, 0); 140b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals("P60M", cv.getAsString(Events.DURATION)); 141b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(startTime, cv.getAsLong(Events.DTSTART)); 142b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsLong(Events.DTEND)); 143b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsLong(Events.LAST_DATE)); 144b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsString(Events.EVENT_TIMEZONE)); 145b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 146b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 147b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testSetTimeRelatedValues_AllDay() throws IOException { 148b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 149b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = adapter.new EasCalendarSyncParser(getTestInputStream(), adapter); 150b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentValues cv = new ContentValues(); 151b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar startCalendar = new GregorianCalendar(2010, 5, 10, 8, 30); 152b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long startTime = startCalendar.getTimeInMillis(); 153b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar endCalendar = new GregorianCalendar(2010, 5, 11, 8, 30); 154b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long endTime = endCalendar.getTimeInMillis(); 155b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.RRULE, "FREQ=WEEKLY;BYDAY=MO"); 156b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.setTimeRelatedValues(cv, startTime, endTime, 1); 157b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 158b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The start time should have hour/min/sec zero'd out 159b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook startCalendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 160b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook startCalendar.set(2010, 5, 10, 0, 0, 0); 161b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook startCalendar.set(GregorianCalendar.MILLISECOND, 0); 162b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook startTime = startCalendar.getTimeInMillis(); 163b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(startTime, cv.getAsLong(Events.DTSTART)); 164b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 165b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The duration should be in days 166b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals("P1D", cv.getAsString(Events.DURATION)); 167b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsLong(Events.DTEND)); 168b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsLong(Events.LAST_DATE)); 169b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // There must be a timezone 170b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNotNull(cv.getAsString(Events.EVENT_TIMEZONE)); 171b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 172b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 173b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testSetTimeRelatedValues_Recurring_AllDay_Exception () throws IOException { 174b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 175b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = adapter.new EasCalendarSyncParser(getTestInputStream(), adapter); 176b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentValues cv = new ContentValues(); 177b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 178b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Recurrence exception for all-day event; the exception is NOT all-day 179b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar startCalendar = new GregorianCalendar(2010, 5, 17, 8, 30); 180b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long startTime = startCalendar.getTimeInMillis(); 181b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar endCalendar = new GregorianCalendar(2010, 5, 17, 9, 30); 182b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long endTime = endCalendar.getTimeInMillis(); 183b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.ORIGINAL_ALL_DAY, 1); 184b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar instanceCalendar = new GregorianCalendar(2010, 5, 17, 8, 30); 185b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.ORIGINAL_INSTANCE_TIME, instanceCalendar.getTimeInMillis()); 186b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.setTimeRelatedValues(cv, startTime, endTime, 0); 187b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 188b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The original instance time should have hour/min/sec zero'd out 189b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook GregorianCalendar testCalendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 190b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook testCalendar.set(2010, 5, 17, 0, 0, 0); 191b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook testCalendar.set(GregorianCalendar.MILLISECOND, 0); 192b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Long testTime = testCalendar.getTimeInMillis(); 193b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(testTime, cv.getAsLong(Events.ORIGINAL_INSTANCE_TIME)); 194b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 195b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The exception isn't all-day, so we should have DTEND and LAST_DATE and no EVENT_TIMEZONE 196b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsString(Events.DURATION)); 197b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(endTime, cv.getAsLong(Events.DTEND)); 198b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(endTime, cv.getAsLong(Events.LAST_DATE)); 199b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertNull(cv.getAsString(Events.EVENT_TIMEZONE)); 200b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 201b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 202b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testIsValidEventValues() throws IOException { 203b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter adapter = getTestSyncAdapter(CalendarSyncAdapter.class); 204b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = adapter.new EasCalendarSyncParser(getTestInputStream(), adapter); 205b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 206b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook long validTime = System.currentTimeMillis(); 207b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook String validData = "foo-bar-bletch"; 208b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook String validDuration = "P30M"; 209b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook String validRrule = "FREQ=DAILY"; 210b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 211b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentValues cv = new ContentValues(); 212b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 213b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DTSTART, validTime); 214b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Needs _SYNC_DATA and DTEND/DURATION 215b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 216b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.SYNC_DATA2, validData); 217b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Needs DTEND/DURATION since not an exception 218b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 219b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DURATION, validDuration); 220b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Valid (DTSTART, _SYNC_DATA, DURATION) 221b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertTrue(p.isValidEventValues(cv)); 222b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.remove(Events.DURATION); 223b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.ORIGINAL_INSTANCE_TIME, validTime); 224b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Needs DTEND since it's an exception 225b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 226b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DTEND, validTime); 227b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Valid (DTSTART, DTEND, ORIGINAL_INSTANCE_TIME) 228b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.remove(Events.ORIGINAL_INSTANCE_TIME); 229b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Valid (DTSTART, _SYNC_DATA, DTEND) 230b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertTrue(p.isValidEventValues(cv)); 231b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.remove(Events.DTSTART); 232b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Needs DTSTART 233b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 234b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DTSTART, validTime); 235b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.RRULE, validRrule); 236b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // With RRULE, needs DURATION 237b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 238b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DURATION, "P30M"); 239b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Valid (DTSTART, RRULE, DURATION) 240b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertTrue(p.isValidEventValues(cv)); 241b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.ALL_DAY, "1"); 242b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Needs DURATION in the form P<n>D 243b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertFalse(p.isValidEventValues(cv)); 244b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Valid (DTSTART, RRULE, ALL_DAY, DURATION(P<n>D) 245b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cv.put(Events.DURATION, "P1D"); 246b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertTrue(p.isValidEventValues(cv)); 247b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 248b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 249b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private void addAttendeesToSerializer(Serializer s, int num) throws IOException { 250b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook for (int i = 0; i < num; i++) { 251b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.start(Tags.CALENDAR_ATTENDEE); 252b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_EMAIL, "frederick" + num + 253b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ".flintstone@this.that.verylongservername.com"); 254b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_TYPE, "1"); 255b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_NAME, "Frederick" + num + " Flintstone, III"); 256b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.end(); 257b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 258b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 259b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 260b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private void addAttendeeToSerializer(Serializer s, String email, String name) 261b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook throws IOException { 262b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.start(Tags.CALENDAR_ATTENDEE); 263b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_EMAIL, email); 264b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_TYPE, "1"); 265b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.data(Tags.CALENDAR_ATTENDEE_NAME, name); 266b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook s.end(); 267b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 268b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 269b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private int countInsertOperationsForTable(CalendarOperations ops, String tableName) { 270b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook int cnt = 0; 271b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook for (Operation op: ops) { 272b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentProviderOperation cpo = 273b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook AbstractSyncAdapter.operationToContentProviderOperation(op, 0); 274b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook List<String> segments = cpo.getUri().getPathSegments(); 275b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (segments.get(0).equalsIgnoreCase(tableName) && 276b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cpo.getType() == ContentProviderOperation.TYPE_INSERT) { 277b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cnt++; 278b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 279b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 280b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return cnt; 281b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 282b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 283b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook class TestEvent extends Serializer { 284b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook CalendarSyncAdapter mAdapter; 285b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser mParser; 286b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Serializer mSerializer; 287b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 288b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent() throws IOException { 289b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook super(false); 290b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mAdapter = getTestSyncAdapter(CalendarSyncAdapter.class); 291b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mParser = mAdapter.new EasCalendarSyncParser(getTestInputStream(), mAdapter); 292b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 293b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 294b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook void setUserEmailAddress(String addr) { 295b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mAdapter.mAccount.mEmailAddress = addr; 296b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mAdapter.mEmailAddress = addr; 297b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 298b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 299b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser getParser() throws IOException { 300b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Set up our parser's input and eat the initial tag 301b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mParser.resetInput(new ByteArrayInputStream(toByteArray())); 302b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mParser.nextTag(0); 303b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return mParser; 304b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 305b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 306b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // setupPreAttendees and setupPostAttendees initialize calendar data in the order in which 307b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // they would appear in an actual EAS session. Between these two calls, we initialize 308b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // attendee data, which varies between the following tests 309b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent setupPreAttendees() throws IOException { 310b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook start(Tags.SYNC_APPLICATION_DATA); 311b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_TIME_ZONE, TEST_TIME_ZONE); 312b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_DTSTAMP, "20100518T213156Z"); 313b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_START_TIME, "20100518T220000Z"); 314b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_SUBJECT, "Documentation"); 315b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_UID, "4417556B-27DE-4ECE-B679-A63EFE1F9E85"); 316b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_ORGANIZER_NAME, "Fred Squatibuquitas"); 317b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_ORGANIZER_EMAIL, "fred.squatibuquitas@prettylongdomainname.com"); 318b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return this; 319b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 320b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 321b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent setupPostAttendees()throws IOException { 322b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_LOCATION, "CR SF 601T2/North Shore Presentation Self Service (16)"); 323b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_END_TIME, "20100518T223000Z"); 324b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook start(Tags.BASE_BODY); 325b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.BASE_BODY_PREFERENCE, "1"); 326b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.BASE_ESTIMATED_DATA_SIZE, "69105"); // The number is ignored by the parser 327b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.BASE_DATA, 328b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook "This is the event description; we should probably make it longer"); 329b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook end(); // BASE_BODY 330b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook start(Tags.CALENDAR_RECURRENCE); 331b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_RECURRENCE_TYPE, "1"); // weekly 332b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_RECURRENCE_INTERVAL, "1"); 333b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_RECURRENCE_OCCURRENCES, "10"); 334b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_RECURRENCE_DAYOFWEEK, "12"); // tue, wed 335b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_RECURRENCE_UNTIL, "2005-04-14T00:00:00.000Z"); 336b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook end(); // CALENDAR_RECURRENCE 337b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_SENSITIVITY, "0"); 338b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_BUSY_STATUS, "2"); 339b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_ALL_DAY_EVENT, "0"); 340b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.CALENDAR_MEETING_STATUS, "3"); 341b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook data(Tags.BASE_NATIVE_BODY_TYPE, "3"); 342b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook end().done(); // SYNC_APPLICATION_DATA 343b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return this; 344b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 345b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 346b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 347b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEvent() throws IOException { 348b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent event = new TestEvent(); 349b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPreAttendees(); 350b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.start(Tags.CALENDAR_ATTENDEES); 351b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook addAttendeesToSerializer(event, 10); 352b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.end(); // CALENDAR_ATTENDEES 353b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPostAttendees(); 354b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 355b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = event.getParser(); 356b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.addEvent(p.mOps, "1:1", false); 357b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // There should be 1 event 358b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(1, countInsertOperationsForTable(p.mOps, "events")); 359b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Two attendees (organizer and 10 attendees) 360b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(11, countInsertOperationsForTable(p.mOps, "attendees")); 361b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // dtstamp, meeting status, attendees, attendees redacted, and upsync prohibited 362b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(5, countInsertOperationsForTable(p.mOps, "extendedproperties")); 363b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 364b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 365b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEventIllegal() throws IOException { 366b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // We don't send a start time; the event is illegal and nothing should be added 367b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent event = new TestEvent(); 368b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.start(Tags.SYNC_APPLICATION_DATA); 369b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_TIME_ZONE, TEST_TIME_ZONE); 370b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_DTSTAMP, "20100518T213156Z"); 371b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_SUBJECT, "Documentation"); 372b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_UID, "4417556B-27DE-4ECE-B679-A63EFE1F9E85"); 373b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_ORGANIZER_NAME, "Fred Squatibuquitas"); 374b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.data(Tags.CALENDAR_ORGANIZER_EMAIL, "fred.squatibuquitas@prettylongdomainname.com"); 375b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.start(Tags.CALENDAR_ATTENDEES); 376b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook addAttendeesToSerializer(event, 10); 377b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.end(); // CALENDAR_ATTENDEES 378b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPostAttendees(); 379b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 380b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = event.getParser(); 381b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.addEvent(p.mOps, "1:1", false); 382b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(0, countInsertOperationsForTable(p.mOps, "events")); 383b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(0, countInsertOperationsForTable(p.mOps, "attendees")); 384b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(0, countInsertOperationsForTable(p.mOps, "extendedproperties")); 385b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 386b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 387b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEventRedactedAttendees() throws IOException { 388b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent event = new TestEvent(); 389b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPreAttendees(); 390b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.start(Tags.CALENDAR_ATTENDEES); 391b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook addAttendeesToSerializer(event, 100); 392b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.end(); // CALENDAR_ATTENDEES 393b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPostAttendees(); 394b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 395b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = event.getParser(); 396b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.addEvent(p.mOps, "1:1", false); 397b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // There should be 1 event 398b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(1, countInsertOperationsForTable(p.mOps, "events")); 399b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // One attendees (organizer; all others are redacted) 400b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(1, countInsertOperationsForTable(p.mOps, "attendees")); 401b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // dtstamp, meeting status, and attendees redacted 402b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(3, countInsertOperationsForTable(p.mOps, "extendedproperties")); 403b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 404b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 405b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook /** 406b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Setup for the following three tests, which check attendee status of an added event 407b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @param userEmail the email address of the user 408b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @param update whether or not the event is an update (rather than new) 409b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @return a Cursor to the Attendee records added to our MockProvider 410b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @throws IOException 411b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @throws RemoteException 412b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * @throws OperationApplicationException 413b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook */ 414b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private Cursor setupAddEventOneAttendee(String userEmail, boolean update) 415b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook throws IOException, RemoteException, OperationApplicationException { 416b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook TestEvent event = new TestEvent(); 417b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPreAttendees(); 418b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.start(Tags.CALENDAR_ATTENDEES); 419b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook addAttendeeToSerializer(event, SINGLE_ATTENDEE_EMAIL, SINGLE_ATTENDEE_NAME); 420b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setUserEmailAddress(userEmail); 421b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.end(); // CALENDAR_ATTENDEES 422b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook event.setupPostAttendees(); 423b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 424b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook EasCalendarSyncParser p = event.getParser(); 425b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook p.addEvent(p.mOps, "1:1", update); 426b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Send the CPO's to the mock provider 427b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ArrayList<ContentProviderOperation> cpos = new ArrayList<ContentProviderOperation>(); 428b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook for (Operation op: p.mOps) { 429b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook cpos.add(AbstractSyncAdapter.operationToContentProviderOperation(op, 0)); 430b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 431b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mMockResolver.applyBatch(MockProvider.AUTHORITY, cpos); 432b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return mMockResolver.query(MockProvider.uri(Attendees.CONTENT_URI), ATTENDEE_PROJECTION, 433b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook null, null, null); 434b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 435b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 436b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEventOneAttendee() throws IOException, RemoteException, 437b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook OperationApplicationException { 438b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Cursor c = setupAddEventOneAttendee("foo@bar.com", false); 439b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(2, c.getCount()); 440b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The organizer should be "accepted", the unknown attendee "none" 441b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook while (c.moveToNext()) { 442b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (SINGLE_ATTENDEE_EMAIL.equals(c.getString(ATTENDEE_EMAIL))) { 443b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_NONE, c.getInt(ATTENDEE_STATUS)); 444b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } else { 445b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, c.getInt(ATTENDEE_STATUS)); 446b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 447b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 448b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 449b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 450b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEventSelfAttendee() throws IOException, RemoteException, 451b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook OperationApplicationException { 452b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Cursor c = setupAddEventOneAttendee(SINGLE_ATTENDEE_EMAIL, false); 453b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The organizer should be "accepted", and our user/attendee should be "done" even though 454b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // the busy status = 2 (because we can't tell from a status of 2 on new events) 455b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook while (c.moveToNext()) { 456b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (SINGLE_ATTENDEE_EMAIL.equals(c.getString(ATTENDEE_EMAIL))) { 457b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_NONE, c.getInt(ATTENDEE_STATUS)); 458b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } else { 459b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, c.getInt(ATTENDEE_STATUS)); 460b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 461b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 462b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 463b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 464b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void testAddEventSelfAttendeeUpdate() throws IOException, RemoteException, 465b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook OperationApplicationException { 466b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Cursor c = setupAddEventOneAttendee(SINGLE_ATTENDEE_EMAIL, true); 467b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // The organizer should be "accepted", and our user/attendee should be "accepted" (because 468b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // busy status = 2 and this is an update 469b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook while (c.moveToNext()) { 470b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (SINGLE_ATTENDEE_EMAIL.equals(c.getString(ATTENDEE_EMAIL))) { 471b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, c.getInt(ATTENDEE_STATUS)); 472b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } else { 473b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, c.getInt(ATTENDEE_STATUS)); 474b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 475b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 476b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 477b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook} 478