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