/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.provider.cts;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.content.EntityIterator;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.CalendarEntity;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Colors;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.EventsEntity;
import android.provider.CalendarContract.ExtendedProperties;
import android.provider.CalendarContract.Instances;
import android.provider.CalendarContract.Reminders;
import android.provider.CalendarContract.SyncState;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;

import com.android.compatibility.common.util.PollingCheck;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CalendarTest extends InstrumentationTestCase {

    private static final String TAG = "CalCTS";
    private static final String CTS_TEST_TYPE = "LOCAL";

    // an arbitrary int used by some tests
    private static final int SOME_ARBITRARY_INT = 143234;

    // 15 sec timeout for reminder broadcast (but shouldn't usually take this long).
    private static final int POLLING_TIMEOUT = 15000;

    // @formatter:off
    private static final String[] TIME_ZONES = new String[] {
            "UTC",
            "America/Los_Angeles",
            "Asia/Beirut",
            "Pacific/Auckland", };
    // @formatter:on

    private static final String SQL_WHERE_ID = Events._ID + "=?";
    private static final String SQL_WHERE_CALENDAR_ID = Events.CALENDAR_ID + "=?";

    private ContentResolver mContentResolver;

    /** If set, log verbose instance info when running recurrence tests. */
    private static final boolean DEBUG_RECURRENCE = false;

    private static class CalendarHelper {

        // @formatter:off
        public static final String[] CALENDARS_SYNC_PROJECTION = new String[] {
                Calendars._ID,
                Calendars.ACCOUNT_NAME,
                Calendars.ACCOUNT_TYPE,
                Calendars._SYNC_ID,
                Calendars.CAL_SYNC7,
                Calendars.CAL_SYNC8,
                Calendars.DIRTY,
                Calendars.NAME,
                Calendars.CALENDAR_DISPLAY_NAME,
                Calendars.CALENDAR_COLOR,
                Calendars.CALENDAR_COLOR_KEY,
                Calendars.CALENDAR_ACCESS_LEVEL,
                Calendars.VISIBLE,
                Calendars.SYNC_EVENTS,
                Calendars.CALENDAR_LOCATION,
                Calendars.CALENDAR_TIME_ZONE,
                Calendars.OWNER_ACCOUNT,
                Calendars.CAN_ORGANIZER_RESPOND,
                Calendars.CAN_MODIFY_TIME_ZONE,
                Calendars.MAX_REMINDERS,
                Calendars.ALLOWED_REMINDERS,
                Calendars.ALLOWED_AVAILABILITY,
                Calendars.ALLOWED_ATTENDEE_TYPES,
                Calendars.DELETED,
                Calendars.CAL_SYNC1,
                Calendars.CAL_SYNC2,
                Calendars.CAL_SYNC3,
                Calendars.CAL_SYNC4,
                Calendars.CAL_SYNC5,
                Calendars.CAL_SYNC6,
                };
        // @formatter:on

        private CalendarHelper() {}     // do not instantiate this class

        /**
         * Generates the e-mail address for the Calendar owner.  Use this for
         * Calendars.OWNER_ACCOUNT, Events.OWNER_ACCOUNT, and for Attendees.ATTENDEE_EMAIL
         * when you want a "self" attendee entry.
         */
        static String generateCalendarOwnerEmail(String account) {
            return "OWNER_" + account + "@example.com";
        }

        /**
         * Creates a new set of values for creating a single calendar with every
         * field.
         *
         * @param account The account name to create this calendar with
         * @param seed A number used to generate the values
         * @return A complete set of values for the calendar
         */
        public static ContentValues getNewCalendarValues(
                String account, int seed) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();
            values.put(Calendars.ACCOUNT_TYPE, CTS_TEST_TYPE);

            values.put(Calendars.ACCOUNT_NAME, account);
            values.put(Calendars._SYNC_ID, "SYNC_ID:" + seedString);
            values.put(Calendars.CAL_SYNC7, "SYNC_V:" + seedString);
            values.put(Calendars.CAL_SYNC8, "SYNC_TIME:" + seedString);
            values.put(Calendars.DIRTY, 0);
            values.put(Calendars.OWNER_ACCOUNT, generateCalendarOwnerEmail(account));

            values.put(Calendars.NAME, seedString);
            values.put(Calendars.CALENDAR_DISPLAY_NAME, "DISPLAY_" + seedString);

            values.put(Calendars.CALENDAR_ACCESS_LEVEL, (seed % 8) * 100);

            values.put(Calendars.CALENDAR_COLOR, 0xff000000 + seed);
            values.put(Calendars.VISIBLE, seed % 2);
            values.put(Calendars.SYNC_EVENTS, 1);   // must be 1 for recurrence expansion
            values.put(Calendars.CALENDAR_LOCATION, "LOCATION:" + seedString);
            values.put(Calendars.CALENDAR_TIME_ZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            values.put(Calendars.CAN_ORGANIZER_RESPOND, seed % 2);
            values.put(Calendars.CAN_MODIFY_TIME_ZONE, seed % 2);
            values.put(Calendars.MAX_REMINDERS, 3);
            values.put(Calendars.ALLOWED_REMINDERS, "0,1,2");   // does not include SMS (3)
            values.put(Calendars.ALLOWED_ATTENDEE_TYPES, "0,1,2,3");
            values.put(Calendars.ALLOWED_AVAILABILITY, "0,1,2,3");
            values.put(Calendars.CAL_SYNC1, "SYNC1:" + seedString);
            values.put(Calendars.CAL_SYNC2, "SYNC2:" + seedString);
            values.put(Calendars.CAL_SYNC3, "SYNC3:" + seedString);
            values.put(Calendars.CAL_SYNC4, "SYNC4:" + seedString);
            values.put(Calendars.CAL_SYNC5, "SYNC5:" + seedString);
            values.put(Calendars.CAL_SYNC6, "SYNC6:" + seedString);

            return values;
        }

        /**
         * Creates a set of values with just the updates and modifies the
         * original values to the expected values
         */
        public static ContentValues getUpdateCalendarValuesWithOriginal(
                ContentValues original, int seed) {
            ContentValues values = new ContentValues();
            String seedString = Long.toString(seed);

            values.put(Calendars.CALENDAR_DISPLAY_NAME, "DISPLAY_" + seedString);
            values.put(Calendars.CALENDAR_COLOR, 0xff000000 + seed);
            values.put(Calendars.VISIBLE, seed % 2);
            values.put(Calendars.SYNC_EVENTS, seed % 2);

            original.putAll(values);
            original.put(Calendars.DIRTY, 1);

            return values;
        }

        public static int deleteCalendarById(ContentResolver resolver, long id) {
            return resolver.delete(Calendars.CONTENT_URI, Calendars._ID + "=?",
                    new String[] { Long.toString(id) });
        }

        public static int deleteCalendarByAccount(ContentResolver resolver, String account) {
            return resolver.delete(Calendars.CONTENT_URI, Calendars.ACCOUNT_NAME + "=?",
                    new String[] { account });
        }

        public static Cursor getCalendarsByAccount(ContentResolver resolver, String account) {
            String selection = Calendars.ACCOUNT_TYPE + "=?";
            String[] selectionArgs;
            if (account != null) {
                selection += " AND " + Calendars.ACCOUNT_NAME + "=?";
                selectionArgs = new String[2];
                selectionArgs[1] = account;
            } else {
                selectionArgs = new String[1];
            }
            selectionArgs[0] = CTS_TEST_TYPE;

            return resolver.query(Calendars.CONTENT_URI, CALENDARS_SYNC_PROJECTION, selection,
                    selectionArgs, null);
        }
    }

    /**
     * Helper class for manipulating entries in the _sync_state table.
     */
    private static class SyncStateHelper {
        public static final String[] SYNCSTATE_PROJECTION = new String[] {
            SyncState._ID,
            SyncState.ACCOUNT_NAME,
            SyncState.ACCOUNT_TYPE,
            SyncState.DATA
        };

        private static final byte[] SAMPLE_SYNC_DATA = {
            (byte) 'H', (byte) 'e', (byte) 'l', (byte) 'l', (byte) 'o'
        };

        private SyncStateHelper() {}      // do not instantiate

        /**
         * Creates a new set of values for creating a new _sync_state entry.
         */
        public static ContentValues getNewSyncStateValues(String account) {
            ContentValues values = new ContentValues();
            values.put(SyncState.DATA, SAMPLE_SYNC_DATA);
            values.put(SyncState.ACCOUNT_NAME, account);
            values.put(SyncState.ACCOUNT_TYPE, CTS_TEST_TYPE);
            return values;
        }

        /**
         * Retrieves the _sync_state entry with the specified ID.
         */
        public static Cursor getSyncStateById(ContentResolver resolver, long id) {
            Uri uri = ContentUris.withAppendedId(SyncState.CONTENT_URI, id);
            return resolver.query(uri, SYNCSTATE_PROJECTION, null, null, null);
        }

        /**
         * Retrieves the _sync_state entry for the specified account.
         */
        public static Cursor getSyncStateByAccount(ContentResolver resolver, String account) {
            assertNotNull(account);
            String selection = SyncState.ACCOUNT_TYPE + "=? AND " + SyncState.ACCOUNT_NAME + "=?";
            String[] selectionArgs = new String[] { CTS_TEST_TYPE, account };

            return resolver.query(SyncState.CONTENT_URI, SYNCSTATE_PROJECTION, selection,
                    selectionArgs, null);
        }

        /**
         * Deletes the _sync_state entry with the specified ID.  Always done as app.
         */
        public static int deleteSyncStateById(ContentResolver resolver, long id) {
            Uri uri = ContentUris.withAppendedId(SyncState.CONTENT_URI, id);
            return resolver.delete(uri, null, null);
        }

        /**
         * Deletes the _sync_state entry associated with the specified account.  Can be done
         * as app or sync adapter.
         */
        public static int deleteSyncStateByAccount(ContentResolver resolver, String account,
                boolean asSyncAdapter) {
            Uri uri = SyncState.CONTENT_URI;
            if (asSyncAdapter) {
                uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
            }
            return resolver.delete(uri, SyncState.ACCOUNT_NAME + "=?",
                    new String[] { account });
        }
    }

    // @formatter:off
    private static class EventHelper {
        public static final String[] EVENTS_PROJECTION = new String[] {
            Events._ID,
            Events.ACCOUNT_NAME,
            Events.ACCOUNT_TYPE,
            Events.OWNER_ACCOUNT,
            // Events.ORGANIZER_CAN_RESPOND, from Calendars
            // Events.CAN_CHANGE_TZ, from Calendars
            // Events.MAX_REMINDERS, from Calendars
            Events.CALENDAR_ID,
            // Events.CALENDAR_DISPLAY_NAME, from Calendars
            // Events.CALENDAR_COLOR, from Calendars
            // Events.CALENDAR_ACL, from Calendars
            // Events.CALENDAR_VISIBLE, from Calendars
            Events.SYNC_DATA3,
            Events.SYNC_DATA6,
            Events.TITLE,
            Events.EVENT_LOCATION,
            Events.DESCRIPTION,
            Events.STATUS,
            Events.SELF_ATTENDEE_STATUS,
            Events.DTSTART,
            Events.DTEND,
            Events.EVENT_TIMEZONE,
            Events.EVENT_END_TIMEZONE,
            Events.EVENT_COLOR,
            Events.EVENT_COLOR_KEY,
            Events.DURATION,
            Events.ALL_DAY,
            Events.ACCESS_LEVEL,
            Events.AVAILABILITY,
            Events.HAS_ALARM,
            Events.HAS_EXTENDED_PROPERTIES,
            Events.RRULE,
            Events.RDATE,
            Events.EXRULE,
            Events.EXDATE,
            Events.ORIGINAL_ID,
            Events.ORIGINAL_SYNC_ID,
            Events.ORIGINAL_INSTANCE_TIME,
            Events.ORIGINAL_ALL_DAY,
            Events.LAST_DATE,
            Events.HAS_ATTENDEE_DATA,
            Events.GUESTS_CAN_MODIFY,
            Events.GUESTS_CAN_INVITE_OTHERS,
            Events.GUESTS_CAN_SEE_GUESTS,
            Events.ORGANIZER,
            Events.DELETED,
            Events._SYNC_ID,
            Events.SYNC_DATA4,
            Events.SYNC_DATA5,
            Events.DIRTY,
            Events.SYNC_DATA8,
            Events.SYNC_DATA2,
            Events.SYNC_DATA1,
            Events.SYNC_DATA2,
            Events.SYNC_DATA3,
            Events.SYNC_DATA4,
            Events.MUTATORS,
        };
        // @formatter:on

        private EventHelper() {}    // do not instantiate this class

        /**
         * Constructs a set of name/value pairs that can be used to create a Calendar event.
         * Various fields are generated from the seed value.
         */
        public static ContentValues getNewEventValues(
                String account, int seed, long calendarId, boolean asSyncAdapter) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();
            values.put(Events.ORGANIZER, "ORGANIZER:" + seedString);

            values.put(Events.TITLE, "TITLE:" + seedString);
            values.put(Events.EVENT_LOCATION, "LOCATION_" + seedString);

            values.put(Events.CALENDAR_ID, calendarId);

            values.put(Events.DESCRIPTION, "DESCRIPTION:" + seedString);
            values.put(Events.STATUS, seed % 2);    // avoid STATUS_CANCELED for general testing

            values.put(Events.DTSTART, seed);
            values.put(Events.DTEND, seed + DateUtils.HOUR_IN_MILLIS);
            values.put(Events.EVENT_TIMEZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            values.put(Events.EVENT_COLOR, seed);
            // values.put(Events.EVENT_TIMEZONE2, TIME_ZONES[(seed +1) %
            // TIME_ZONES.length]);
            if ((seed % 2) == 0) {
                // Either set to zero, or leave unset to get default zero.
                // Must be 0 or dtstart/dtend will get adjusted.
                values.put(Events.ALL_DAY, 0);
            }
            values.put(Events.ACCESS_LEVEL, seed % 4);
            values.put(Events.AVAILABILITY, seed % 2);
            values.put(Events.HAS_EXTENDED_PROPERTIES, seed % 2);
            values.put(Events.HAS_ATTENDEE_DATA, seed % 2);
            values.put(Events.GUESTS_CAN_MODIFY, seed % 2);
            values.put(Events.GUESTS_CAN_INVITE_OTHERS, seed % 2);
            values.put(Events.GUESTS_CAN_SEE_GUESTS, seed % 2);

            // Default is STATUS_TENTATIVE (0).  We either set it to that explicitly, or leave
            // it set to the default.
            if (seed != Events.STATUS_TENTATIVE) {
                values.put(Events.SELF_ATTENDEE_STATUS, Events.STATUS_TENTATIVE);
            }

            if (asSyncAdapter) {
                values.put(Events._SYNC_ID, "SYNC_ID:" + seedString);
                values.put(Events.SYNC_DATA4, "SYNC_V:" + seedString);
                values.put(Events.SYNC_DATA5, "SYNC_TIME:" + seedString);
                values.put(Events.SYNC_DATA3, "HTML:" + seedString);
                values.put(Events.SYNC_DATA6, "COMMENTS:" + seedString);
                values.put(Events.DIRTY, 0);
                values.put(Events.SYNC_DATA8, "0");
            } else {
                // only the sync adapter can set the DIRTY flag
                //values.put(Events.DIRTY, 1);
            }
            // values.put(Events.SYNC1, "SYNC1:" + seedString);
            // values.put(Events.SYNC2, "SYNC2:" + seedString);
            // values.put(Events.SYNC3, "SYNC3:" + seedString);
            // values.put(Events.SYNC4, "SYNC4:" + seedString);
            // values.put(Events.SYNC5, "SYNC5:" + seedString);
//            Events.RRULE,
//            Events.RDATE,
//            Events.EXRULE,
//            Events.EXDATE,
//            // Events.ORIGINAL_ID
//            Events.ORIGINAL_EVENT, // rename ORIGINAL_SYNC_ID
//            Events.ORIGINAL_INSTANCE_TIME,
//            Events.ORIGINAL_ALL_DAY,

            return values;
        }

        /**
         * Constructs a set of name/value pairs that can be used to create a recurring
         * Calendar event.
         *
         * A duration of "P1D" is treated as an all-day event.
         *
         * @param startWhen Starting date/time in RFC 3339 format
         * @param duration Event duration, in RFC 2445 duration format
         * @param rrule Recurrence rule
         * @return name/value pairs to use when creating event
         */
        public static ContentValues getNewRecurringEventValues(String account, int seed,
                long calendarId, boolean asSyncAdapter, String startWhen, String duration,
                String rrule) {

            // Set up some general stuff.
            ContentValues values = getNewEventValues(account, seed, calendarId, asSyncAdapter);

            // Replace the DTSTART field.
            String timeZone = values.getAsString(Events.EVENT_TIMEZONE);
            Time time = new Time(timeZone);
            time.parse3339(startWhen);
            values.put(Events.DTSTART, time.toMillis(false));

            // Add in the recurrence-specific fields, and drop DTEND.
            values.put(Events.RRULE, rrule);
            values.put(Events.DURATION, duration);
            values.remove(Events.DTEND);

            return values;
        }

        /**
         * Constructs the basic name/value pairs required for an exception to a recurring event.
         *
         * @param instanceStartMillis The start time of the instance
         * @return name/value pairs to use when creating event
         */
        public static ContentValues getNewExceptionValues(long instanceStartMillis) {
            ContentValues values = new ContentValues();
            values.put(Events.ORIGINAL_INSTANCE_TIME, instanceStartMillis);

            return values;
        }

        public static ContentValues getUpdateEventValuesWithOriginal(ContentValues original,
                int seed, boolean asSyncAdapter) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();

            values.put(Events.TITLE, "TITLE:" + seedString);
            values.put(Events.EVENT_LOCATION, "LOCATION_" + seedString);
            values.put(Events.DESCRIPTION, "DESCRIPTION:" + seedString);
            values.put(Events.STATUS, seed % 3);

            values.put(Events.DTSTART, seed);
            values.put(Events.DTEND, seed + DateUtils.HOUR_IN_MILLIS);
            values.put(Events.EVENT_TIMEZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            // values.put(Events.EVENT_TIMEZONE2, TIME_ZONES[(seed +1) %
            // TIME_ZONES.length]);
            values.put(Events.ACCESS_LEVEL, seed % 4);
            values.put(Events.AVAILABILITY, seed % 2);
            values.put(Events.HAS_EXTENDED_PROPERTIES, seed % 2);
            values.put(Events.HAS_ATTENDEE_DATA, seed % 2);
            values.put(Events.GUESTS_CAN_MODIFY, seed % 2);
            values.put(Events.GUESTS_CAN_INVITE_OTHERS, seed % 2);
            values.put(Events.GUESTS_CAN_SEE_GUESTS, seed % 2);
            if (asSyncAdapter) {
                values.put(Events._SYNC_ID, "SYNC_ID:" + seedString);
                values.put(Events.SYNC_DATA4, "SYNC_V:" + seedString);
                values.put(Events.SYNC_DATA5, "SYNC_TIME:" + seedString);
                values.put(Events.DIRTY, 0);
            }
            original.putAll(values);
            return values;
        }

        public static void addDefaultReadOnlyValues(ContentValues values, String account,
                boolean asSyncAdapter) {
            values.put(Events.SELF_ATTENDEE_STATUS, Events.STATUS_TENTATIVE);
            values.put(Events.DELETED, 0);
            values.put(Events.DIRTY, asSyncAdapter ? 0 : 1);
            values.put(Events.OWNER_ACCOUNT, CalendarHelper.generateCalendarOwnerEmail(account));
            values.put(Events.ACCOUNT_TYPE, CTS_TEST_TYPE);
            values.put(Events.ACCOUNT_NAME, account);
        }

        /**
         * Generates a RFC2445-format duration string.
         */
        private static String generateDurationString(long durationMillis, boolean isAllDay) {
            long durationSeconds = durationMillis / 1000;

            // The server may react differently to an all-day event specified as "P1D" than
            // it will to "PT86400S"; see b/1594638.
            if (isAllDay && (durationSeconds % 86400) == 0) {
                return "P" + durationSeconds / 86400 + "D";
            } else {
                return "PT" + durationSeconds + "S";
            }
        }

        /**
         * Deletes the event, and updates the values.
         * @param resolver The resolver to issue the query against.
         * @param uri The deletion URI.
         * @param values Set of values to update (sets DELETED and DIRTY).
         * @return The number of rows modified.
         */
        public static int deleteEvent(ContentResolver resolver, Uri uri, ContentValues values) {
            values.put(Events.DELETED, 1);
            values.put(Events.DIRTY, 1);
            return resolver.delete(uri, null, null);
        }

        public static int deleteEventAsSyncAdapter(ContentResolver resolver, Uri uri,
                String account) {
            Uri syncUri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
            return resolver.delete(syncUri, null, null);
        }

        public static Cursor getEventsByAccount(ContentResolver resolver, String account) {
            String selection = Calendars.ACCOUNT_TYPE + "=?";
            String[] selectionArgs;
            if (account != null) {
                selection += " AND " + Calendars.ACCOUNT_NAME + "=?";
                selectionArgs = new String[2];
                selectionArgs[1] = account;
            } else {
                selectionArgs = new String[1];
            }
            selectionArgs[0] = CTS_TEST_TYPE;
            return resolver.query(Events.CONTENT_URI, EVENTS_PROJECTION, selection, selectionArgs,
                    null);
        }

        public static Cursor getEventByUri(ContentResolver resolver, Uri uri) {
            return resolver.query(uri, EVENTS_PROJECTION, null, null, null);
        }

        /**
         * Looks up the specified Event in the database and returns the "selfAttendeeStatus"
         * value.
         */
        public static int lookupSelfAttendeeStatus(ContentResolver resolver, long eventId) {
            return getIntFromDatabase(resolver, Events.CONTENT_URI, eventId,
                    Events.SELF_ATTENDEE_STATUS);
        }

        /**
         * Looks up the specified Event in the database and returns the "hasAlarm"
         * value.
         */
        public static int lookupHasAlarm(ContentResolver resolver, long eventId) {
            return getIntFromDatabase(resolver, Events.CONTENT_URI, eventId,
                    Events.HAS_ALARM);
        }
    }

    /**
     * Helper class for manipulating entries in the Attendees table.
     */
    private static class AttendeeHelper {
        public static final String[] ATTENDEES_PROJECTION = new String[] {
            Attendees._ID,
            Attendees.EVENT_ID,
            Attendees.ATTENDEE_NAME,
            Attendees.ATTENDEE_EMAIL,
            Attendees.ATTENDEE_STATUS,
            Attendees.ATTENDEE_RELATIONSHIP,
            Attendees.ATTENDEE_TYPE
        };
        // indexes into projection
        public static final int ATTENDEES_ID_INDEX = 0;
        public static final int ATTENDEES_EVENT_ID_INDEX = 1;

        // do not instantiate
        private AttendeeHelper() {}

        /**
         * Adds a new attendee to the specified event.
         *
         * @return the _id of the new attendee, or -1 on failure
         */
        public static long addAttendee(ContentResolver resolver, long eventId, String name,
                String email, int status, int relationship, int type) {
            Uri uri = Attendees.CONTENT_URI;

            ContentValues attendee = new ContentValues();
            attendee.put(Attendees.EVENT_ID, eventId);
            attendee.put(Attendees.ATTENDEE_NAME, name);
            attendee.put(Attendees.ATTENDEE_EMAIL, email);
            attendee.put(Attendees.ATTENDEE_STATUS, status);
            attendee.put(Attendees.ATTENDEE_RELATIONSHIP, relationship);
            attendee.put(Attendees.ATTENDEE_TYPE, type);
            Uri result = resolver.insert(uri, attendee);
            return ContentUris.parseId(result);
        }

        /**
         * Finds all Attendees rows for the specified event and email address.  The returned
         * cursor will use {@link AttendeeHelper#ATTENDEES_PROJECTION}.
         */
        public static Cursor findAttendeesByEmail(ContentResolver resolver, long eventId,
                String email) {
            return resolver.query(Attendees.CONTENT_URI, ATTENDEES_PROJECTION,
                    Attendees.EVENT_ID + "=? AND " + Attendees.ATTENDEE_EMAIL + "=?",
                    new String[] { String.valueOf(eventId), email }, null);
        }
    }

    /**
     * Helper class for manipulating entries in the Colors table.
     */
    private static class ColorHelper {
        public static final String WHERE_COLOR_ACCOUNT = Colors.ACCOUNT_NAME + "=? AND "
                + Colors.ACCOUNT_TYPE + "=?";
        public static final String WHERE_COLOR_ACCOUNT_AND_INDEX = WHERE_COLOR_ACCOUNT + " AND "
                + Colors.COLOR_KEY + "=?";

        public static final String[] COLORS_PROJECTION = new String[] {
                Colors._ID, // 0
                Colors.ACCOUNT_NAME, // 1
                Colors.ACCOUNT_TYPE, // 2
                Colors.DATA, // 3
                Colors.COLOR_TYPE, // 4
                Colors.COLOR_KEY, // 5
                Colors.COLOR, // 6
        };
        // indexes into projection
        public static final int COLORS_ID_INDEX = 0;
        public static final int COLORS_INDEX_INDEX = 5;
        public static final int COLORS_COLOR_INDEX = 6;

        public static final int[] DEFAULT_TYPES = new int[] {
                Colors.TYPE_CALENDAR, Colors.TYPE_CALENDAR, Colors.TYPE_CALENDAR,
                Colors.TYPE_CALENDAR, Colors.TYPE_EVENT, Colors.TYPE_EVENT, Colors.TYPE_EVENT,
                Colors.TYPE_EVENT,
        };
        public static final int[] DEFAULT_COLORS = new int[] {
                0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFAA00AA, 0xFF00AAAA, 0xFF333333, 0xFFAAAA00,
                0xFFAAAAAA,
        };
        public static final String[] DEFAULT_INDICES = new String[] {
                "000", "001", "010", "011", "100", "101", "110", "111",
        };

        public static final int C_COLOR_0 = 0;
        public static final int C_COLOR_1 = 1;
        public static final int C_COLOR_2 = 2;
        public static final int C_COLOR_3 = 3;
        public static final int E_COLOR_0 = 4;
        public static final int E_COLOR_1 = 5;
        public static final int E_COLOR_2 = 6;
        public static final int E_COLOR_3 = 7;

        // do not instantiate
        private ColorHelper() {
        }

        /**
         * Adds a new color to the colors table.
         *
         * @return the _id of the new color, or -1 on failure
         */
        public static long addColor(ContentResolver resolver, String accountName,
                String accountType, String data, String index, int type, int color) {
            Uri uri = asSyncAdapter(Colors.CONTENT_URI, accountName, accountType);

            ContentValues colorValues = new ContentValues();
            colorValues.put(Colors.DATA, data);
            colorValues.put(Colors.COLOR_KEY, index);
            colorValues.put(Colors.COLOR_TYPE, type);
            colorValues.put(Colors.COLOR, color);
            Uri result = resolver.insert(uri, colorValues);
            return ContentUris.parseId(result);
        }

        /**
         * Finds the color specified by an account name/type and a color index.
         * The returned cursor will use {@link ColorHelper#COLORS_PROJECTION}.
         */
        public static Cursor findColorByIndex(ContentResolver resolver, String accountName,
                String accountType, String index) {
            return resolver.query(Colors.CONTENT_URI, COLORS_PROJECTION,
                    WHERE_COLOR_ACCOUNT_AND_INDEX,
                    new String[] {accountName, accountType, index}, null);
        }

        public static Cursor findColorsByAccount(ContentResolver resolver, String accountName,
                String accountType) {
            return resolver.query(Colors.CONTENT_URI, COLORS_PROJECTION, WHERE_COLOR_ACCOUNT,
                    new String[] { accountName, accountType }, null);
        }

        /**
         * Adds a default set of test colors to the Colors table under the given
         * account.
         *
         * @return true if the default colors were added successfully
         */
        public static boolean addDefaultColorsToAccount(ContentResolver resolver,
                String accountName, String accountType) {
            for (int i = 0; i < DEFAULT_INDICES.length; i++) {
                long id = addColor(resolver, accountName, accountType, null, DEFAULT_INDICES[i],
                        DEFAULT_TYPES[i], DEFAULT_COLORS[i]);
                if (id == -1) {
                    return false;
                }
            }
            return true;
        }

        public static void deleteColorsByAccount(ContentResolver resolver, String accountName,
                String accountType) {
            Uri uri = asSyncAdapter(Colors.CONTENT_URI, accountName, accountType);
            resolver.delete(uri, WHERE_COLOR_ACCOUNT, new String[] { accountName, accountType });
        }
    }


    /**
     * Helper class for manipulating entries in the Reminders table.
     */
    private static class ReminderHelper {
        public static final String[] REMINDERS_PROJECTION = new String[] {
            Reminders._ID,
            Reminders.EVENT_ID,
            Reminders.MINUTES,
            Reminders.METHOD
        };
        // indexes into projection
        public static final int REMINDERS_ID_INDEX = 0;
        public static final int REMINDERS_EVENT_ID_INDEX = 1;
        public static final int REMINDERS_MINUTES_INDEX = 2;
        public static final int REMINDERS_METHOD_INDEX = 3;

        // do not instantiate
        private ReminderHelper() {}

        /**
         * Adds a new reminder to the specified event.
         *
         * @return the _id of the new reminder, or -1 on failure
         */
        public static long addReminder(ContentResolver resolver, long eventId, int minutes,
                int method) {
            Uri uri = Reminders.CONTENT_URI;

            ContentValues reminder = new ContentValues();
            reminder.put(Reminders.EVENT_ID, eventId);
            reminder.put(Reminders.MINUTES, minutes);
            reminder.put(Reminders.METHOD, method);
            Uri result = resolver.insert(uri, reminder);
            return ContentUris.parseId(result);
        }

        /**
         * Finds all Reminders rows for the specified event.  The returned cursor will use
         * {@link ReminderHelper#REMINDERS_PROJECTION}.
         */
        public static Cursor findRemindersByEventId(ContentResolver resolver, long eventId) {
            return resolver.query(Reminders.CONTENT_URI, REMINDERS_PROJECTION,
                    Reminders.EVENT_ID + "=?", new String[] { String.valueOf(eventId) }, null);
        }

        /**
         * Looks up the specified Reminders row and returns the "method" value.
         */
        public static int lookupMethod(ContentResolver resolver, long remId) {
            return getIntFromDatabase(resolver, Reminders.CONTENT_URI, remId,
                    Reminders.METHOD);
        }
   }

    /**
     * Helper class for manipulating entries in the ExtendedProperties table.
     */
    private static class ExtendedPropertiesHelper {
        public static final String[] EXTENDED_PROPERTIES_PROJECTION = new String[] {
            ExtendedProperties._ID,
            ExtendedProperties.EVENT_ID,
            ExtendedProperties.NAME,
            ExtendedProperties.VALUE
        };
        // indexes into projection
        public static final int EXTENDED_PROPERTIES_ID_INDEX = 0;
        public static final int EXTENDED_PROPERTIES_EVENT_ID_INDEX = 1;
        public static final int EXTENDED_PROPERTIES_NAME_INDEX = 2;
        public static final int EXTENDED_PROPERTIES_VALUE_INDEX = 3;

        // do not instantiate
        private ExtendedPropertiesHelper() {}

        /**
         * Adds a new ExtendedProperty for the specified event.  Runs as sync adapter.
         *
         * @return the _id of the new ExtendedProperty, or -1 on failure
         */
        public static long addExtendedProperty(ContentResolver resolver, String account,
                long eventId, String name, String value) {
             Uri uri = asSyncAdapter(ExtendedProperties.CONTENT_URI, account, CTS_TEST_TYPE);

            ContentValues ep = new ContentValues();
            ep.put(ExtendedProperties.EVENT_ID, eventId);
            ep.put(ExtendedProperties.NAME, name);
            ep.put(ExtendedProperties.VALUE, value);
            Uri result = resolver.insert(uri, ep);
            return ContentUris.parseId(result);
        }

        /**
         * Finds all ExtendedProperties rows for the specified event.  The returned cursor will
         * use {@link ExtendedPropertiesHelper#EXTENDED_PROPERTIES_PROJECTION}.
         */
        public static Cursor findExtendedPropertiesByEventId(ContentResolver resolver,
                long eventId) {
            return resolver.query(ExtendedProperties.CONTENT_URI, EXTENDED_PROPERTIES_PROJECTION,
                    ExtendedProperties.EVENT_ID + "=?",
                    new String[] { String.valueOf(eventId) }, null);
        }

        /**
         * Finds an ExtendedProperties entry with a matching name for the specified event, and
         * returns the value.  Throws an exception if we don't find exactly one row.
         */
        public static String lookupValueByName(ContentResolver resolver, long eventId,
                String name) {
            Cursor cursor = resolver.query(ExtendedProperties.CONTENT_URI,
                    EXTENDED_PROPERTIES_PROJECTION,
                    ExtendedProperties.EVENT_ID + "=? AND " + ExtendedProperties.NAME + "=?",
                    new String[] { String.valueOf(eventId), name }, null);

            try {
                if (cursor.getCount() != 1) {
                    throw new RuntimeException("Got " + cursor.getCount() + " results, expected 1");
                }

                cursor.moveToFirst();
                return cursor.getString(EXTENDED_PROPERTIES_VALUE_INDEX);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
    }

    /**
     * Creates an updated URI that includes query parameters that identify the source as a
     * sync adapter.
     */
    static Uri asSyncAdapter(Uri uri, String account, String accountType) {
        return uri.buildUpon()
                .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,
                        "true")
                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
    }

    /**
     * Returns the value of the specified row and column in the Events table, as an integer.
     * Throws an exception if the specified row or column doesn't exist or doesn't contain
     * an integer (e.g. null entry).
     */
    private static int getIntFromDatabase(ContentResolver resolver, Uri uri, long rowId,
            String columnName) {
        String[] projection = { columnName };
        String selection = SQL_WHERE_ID;
        String[] selectionArgs = { String.valueOf(rowId) };

        Cursor c = resolver.query(uri, projection, selection, selectionArgs, null);
        try {
            assertEquals(1, c.getCount());
            c.moveToFirst();
            return c.getInt(0);
        } finally {
            c.close();
        }
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContentResolver = getInstrumentation().getTargetContext().getContentResolver();
    }

    @MediumTest
    public void testCalendarCreationAndDeletion() {
        String account = "cc1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        long id = createAndVerifyCalendar(account, seed++, null);

        removeAndVerifyCalendar(account, id);
    }

    /**
     * Tests whether the default projections work.  We don't need to have any data in
     * the calendar, since it's testing the database schema.
     */
    @MediumTest
    public void testDefaultProjections() {
        String account = "dproj_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        long id = createAndVerifyCalendar(account, seed++, null);

        Cursor c;
        Uri uri;
        // Calendars
        c = mContentResolver.query(Calendars.CONTENT_URI, null, null, null, null);
        c.close();
        // Events
        c = mContentResolver.query(Events.CONTENT_URI, null, null, null, null);
        c.close();
        // Instances
        uri = Uri.withAppendedPath(Instances.CONTENT_URI, "0/1");
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // Attendees
        c = mContentResolver.query(Attendees.CONTENT_URI, null, null, null, null);
        c.close();
        // Reminders (only REMINDERS_ID currently uses default projection)
        uri = ContentUris.withAppendedId(Reminders.CONTENT_URI, 0);
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // CalendarAlerts
        c = mContentResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI,
                null, null, null, null);
        c.close();
        // CalendarCache
        c = mContentResolver.query(CalendarContract.CalendarCache.URI,
                null, null, null, null);
        c.close();
        // CalendarEntity
        c = mContentResolver.query(CalendarContract.CalendarEntity.CONTENT_URI,
                null, null, null, null);
        c.close();
        // EventEntities
        c = mContentResolver.query(CalendarContract.EventsEntity.CONTENT_URI,
                null, null, null, null);
        c.close();
        // EventDays
        uri = Uri.withAppendedPath(CalendarContract.EventDays.CONTENT_URI, "1/2");
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // ExtendedProperties
        c = mContentResolver.query(CalendarContract.ExtendedProperties.CONTENT_URI,
                null, null, null, null);
        c.close();

        removeAndVerifyCalendar(account, id);
    }

    /**
     * Exercises the EventsEntity class.
     */
    @MediumTest
    public void testEventsEntityQuery() {
        String account = "eeq_account";
        int seed = 0;

        // Clean up just in case.
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar.
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create three events.  We need to make sure SELF_ATTENDEE_STATUS isn't set, because
        // that causes the provider to generate an Attendees entry, and that'll throw off
        // our expected count.
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.remove(Events.SELF_ATTENDEE_STATUS);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId1 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.remove(Events.SELF_ATTENDEE_STATUS);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId2 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.remove(Events.SELF_ATTENDEE_STATUS);
        long eventId3 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId3 >= 0);

        /*
         * Add some attendees, reminders, and extended properties.
         */
        Uri uri, syncUri;

        syncUri = asSyncAdapter(Reminders.CONTENT_URI, account, CTS_TEST_TYPE);
        ContentValues remValues = new ContentValues();
        remValues.put(Reminders.EVENT_ID, eventId1);
        remValues.put(Reminders.MINUTES, 10);
        remValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
        mContentResolver.insert(syncUri, remValues);
        remValues.put(Reminders.MINUTES, 20);
        mContentResolver.insert(syncUri, remValues);

        syncUri = asSyncAdapter(ExtendedProperties.CONTENT_URI, account, CTS_TEST_TYPE);
        ContentValues extended = new ContentValues();
        extended.put(ExtendedProperties.NAME, "foo");
        extended.put(ExtendedProperties.VALUE, "bar");
        extended.put(ExtendedProperties.EVENT_ID, eventId2);
        mContentResolver.insert(syncUri, extended);
        extended.put(ExtendedProperties.EVENT_ID, eventId1);
        mContentResolver.insert(syncUri, extended);
        extended.put(ExtendedProperties.NAME, "foo2");
        extended.put(ExtendedProperties.VALUE, "bar2");
        mContentResolver.insert(syncUri, extended);

        syncUri = asSyncAdapter(Attendees.CONTENT_URI, account, CTS_TEST_TYPE);
        ContentValues attendee = new ContentValues();
        attendee.put(Attendees.ATTENDEE_NAME, "Joe");
        attendee.put(Attendees.ATTENDEE_EMAIL, CalendarHelper.generateCalendarOwnerEmail(account));
        attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED);
        attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        attendee.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_PERFORMER);
        attendee.put(Attendees.EVENT_ID, eventId3);
        mContentResolver.insert(syncUri, attendee);

        /*
         * Iterate over all events on our calendar.  Peek at a few values to see if they
         * look reasonable.
         */
        EntityIterator ei = EventsEntity.newEntityIterator(
                mContentResolver.query(EventsEntity.CONTENT_URI, null, Events.CALENDAR_ID + "=?",
                        new String[] { String.valueOf(calendarId) }, null),
                mContentResolver);
        int count = 0;
        try {
            while (ei.hasNext()) {
                Entity entity = ei.next();
                ContentValues values = entity.getEntityValues();
                ArrayList<Entity.NamedContentValues> subvalues = entity.getSubValues();
                long eventId = values.getAsLong(Events._ID);
                if (eventId == eventId1) {
                    // 2 x reminder, 2 x extended properties
                    assertEquals(4, subvalues.size());
                } else if (eventId == eventId2) {
                    // Extended properties
                    assertEquals(1, subvalues.size());
                    ContentValues subContentValues = subvalues.get(0).values;
                    String name = subContentValues.getAsString(
                            CalendarContract.ExtendedProperties.NAME);
                    String value = subContentValues.getAsString(
                            CalendarContract.ExtendedProperties.VALUE);
                    assertEquals("foo", name);
                    assertEquals("bar", value);
                } else if (eventId == eventId3) {
                    // Attendees
                    assertEquals(1, subvalues.size());
                } else {
                    fail("should not be here");
                }
                count++;
            }
            assertEquals(3, count);
        } finally {
            ei.close();
        }

        // Confirm that querying for a single event yields a single event.
        ei = EventsEntity.newEntityIterator(
                mContentResolver.query(EventsEntity.CONTENT_URI, null, SQL_WHERE_ID,
                        new String[] { String.valueOf(eventId3) }, null),
                mContentResolver);
        try {
            count = 0;
            while (ei.hasNext()) {
                Entity entity = ei.next();
                count++;
            }
            assertEquals(1, count);
        } finally {
            ei.close();
        }


        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Exercises the CalendarEntity class.
     */
    @MediumTest
    public void testCalendarEntityQuery() {
        String account1 = "ceq1_account";
        String account2 = "ceq2_account";
        String account3 = "ceq3_account";
        int seed = 0;

        // Clean up just in case.
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account1);
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account2);
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account3);

        // Create calendars.
        long calendarId1 = createAndVerifyCalendar(account1, seed++, null);
        long calendarId2 = createAndVerifyCalendar(account2, seed++, null);
        long calendarId3 = createAndVerifyCalendar(account3, seed++, null);

        EntityIterator ei = CalendarEntity.newEntityIterator(
                mContentResolver.query(CalendarEntity.CONTENT_URI, null,
                        Calendars._ID + "=? OR " + Calendars._ID + "=? OR " + Calendars._ID + "=?",
                        new String[] { String.valueOf(calendarId1), String.valueOf(calendarId2),
                                String.valueOf(calendarId3) },
                        null));

        try {
            int count = 0;
            while (ei.hasNext()) {
                Entity entity = ei.next();
                count++;
            }
            assertEquals(3, count);
        } finally {
            ei.close();
        }

        removeAndVerifyCalendar(account1, calendarId1);
        removeAndVerifyCalendar(account2, calendarId2);
        removeAndVerifyCalendar(account3, calendarId3);
    }

    /**
     * Tests creation and manipulation of Attendees.
     */
    @MediumTest
    public void testAttendees() {
        String account = "att_account";
        int seed = 0;

        // Clean up just in case.
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar.
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create two events, one with a value set for SELF_ATTENDEE_STATUS, one without.
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.SELF_ATTENDEE_STATUS, Events.STATUS_TENTATIVE);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId1 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.remove(Events.SELF_ATTENDEE_STATUS);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId2 >= 0);

        /*
         * Add some attendees to the first event.
         */
        long attId1 = AttendeeHelper.addAttendee(mContentResolver, eventId1,
                "Alice",
                "alice@example.com",
                Attendees.ATTENDEE_STATUS_TENTATIVE,
                Attendees.RELATIONSHIP_ATTENDEE,
                Attendees.TYPE_REQUIRED);
        long attId2 = AttendeeHelper.addAttendee(mContentResolver, eventId1,
                "Betty",
                "betty@example.com",
                Attendees.ATTENDEE_STATUS_DECLINED,
                Attendees.RELATIONSHIP_ATTENDEE,
                Attendees.TYPE_NONE);
        long attId3 = AttendeeHelper.addAttendee(mContentResolver, eventId1,
                "Carol",
                "carol@example.com",
                Attendees.ATTENDEE_STATUS_DECLINED,
                Attendees.RELATIONSHIP_ATTENDEE,
                Attendees.TYPE_OPTIONAL);

        /*
         * Find the event1 "self" attendee entry.
         */
        Cursor cursor = AttendeeHelper.findAttendeesByEmail(mContentResolver, eventId1,
                CalendarHelper.generateCalendarOwnerEmail(account));
        try {
            assertEquals(1, cursor.getCount());
            //DatabaseUtils.dumpCursor(cursor);

            cursor.moveToFirst();
            long id = cursor.getLong(AttendeeHelper.ATTENDEES_ID_INDEX);

            /*
             * Update the status field.  The provider should automatically propagate the result.
             */
            ContentValues update = new ContentValues();
            Uri uri = ContentUris.withAppendedId(Attendees.CONTENT_URI, id);

            update.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
            int count = mContentResolver.update(uri, update, null, null);
            assertEquals(1, count);

            int status = EventHelper.lookupSelfAttendeeStatus(mContentResolver, eventId1);
            assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, status);

        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        /*
         * Do a bulk update of all Attendees for this event, changing any Attendee with status
         * "declined" to "invited".
         */
        ContentValues bulkUpdate = new ContentValues();
        bulkUpdate.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);

        int count = mContentResolver.update(Attendees.CONTENT_URI, bulkUpdate,
                Attendees.EVENT_ID + "=? AND " + Attendees.ATTENDEE_STATUS + "=?",
                new String[] {
                    String.valueOf(eventId1), String.valueOf(Attendees.ATTENDEE_STATUS_DECLINED)
                });
        assertEquals(2, count);

        /*
         * Add a new, non-self attendee to the second event.
         */
        long attId4 = AttendeeHelper.addAttendee(mContentResolver, eventId2,
                "Diana",
                "diana@example.com",
                Attendees.ATTENDEE_STATUS_ACCEPTED,
                Attendees.RELATIONSHIP_ATTENDEE,
                Attendees.TYPE_REQUIRED);

        /*
         * Confirm that the selfAttendeeStatus on the second event has the default value.
         */
        int status = EventHelper.lookupSelfAttendeeStatus(mContentResolver, eventId2);
        assertEquals(Attendees.ATTENDEE_STATUS_NONE, status);

        /*
         * Create a new "self" attendee in the second event by updating the email address to
         * match that of the calendar owner.
         */
        ContentValues newSelf = new ContentValues();
        newSelf.put(Attendees.ATTENDEE_EMAIL, CalendarHelper.generateCalendarOwnerEmail(account));
        count = mContentResolver.update(ContentUris.withAppendedId(Attendees.CONTENT_URI, attId4),
                newSelf, null, null);
        assertEquals(1, count);

        /*
         * Confirm that the event's selfAttendeeStatus has been updated.
         */
        status = EventHelper.lookupSelfAttendeeStatus(mContentResolver, eventId2);
        assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED, status);

        /*
         * TODO:  (these are unexpected usage patterns)
         * - Update an Attendee's status and event_id to move it to a different event, and
         *   confirm that the selfAttendeeStatus in the destination event is updated (rather
         *   than that of the source event).
         * - Create two Attendees with email addresses that match "self" but have different
         *   values for "status".  Delete one and confirm that selfAttendeeStatus is changed
         *   to that of the remaining Attendee.  (There is no defined behavior for
         *   selfAttendeeStatus when there are multiple matching Attendees.)
         */

        /*
         * Test deletion, singly by ID and in bulk.
         */
        count = mContentResolver.delete(ContentUris.withAppendedId(Attendees.CONTENT_URI, attId4),
                null, null);
        assertEquals(1, count);

        count = mContentResolver.delete(Attendees.CONTENT_URI, Attendees.EVENT_ID + "=?",
                new String[] { String.valueOf(eventId1) });
        assertEquals(4, count);     // 3 we created + 1 auto-added by the provider

        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation and manipulation of Reminders.
     */
    @MediumTest
    public void testReminders() {
        String account = "rem_account";
        int seed = 0;

        // Clean up just in case.
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar.
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create events.
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId1 >= 0);
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId2 >= 0);

        // No reminders, hasAlarm should be zero.
        int hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId1);
        assertEquals(0, hasAlarm);
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId2);
        assertEquals(0, hasAlarm);

        /*
         * Add some reminders.
         */
        long remId1 = ReminderHelper.addReminder(mContentResolver, eventId1,
                10, Reminders.METHOD_DEFAULT);
        long remId2 = ReminderHelper.addReminder(mContentResolver, eventId1,
                15, Reminders.METHOD_ALERT);
        long remId3 = ReminderHelper.addReminder(mContentResolver, eventId1,
                20, Reminders.METHOD_SMS);  // SMS isn't allowed for this calendar

        // Should have been set to 1 by provider.
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId1);
        assertEquals(1, hasAlarm);

        // Add a reminder to event2.
        ReminderHelper.addReminder(mContentResolver, eventId2,
                20, Reminders.METHOD_DEFAULT);
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId2);
        assertEquals(1, hasAlarm);


        /*
         * Check the entries.
         */
        Cursor cursor = ReminderHelper.findRemindersByEventId(mContentResolver, eventId1);
        try {
            assertEquals(3, cursor.getCount());
            //DatabaseUtils.dumpCursor(cursor);

            while (cursor.moveToNext()) {
                int minutes = cursor.getInt(ReminderHelper.REMINDERS_MINUTES_INDEX);
                int method = cursor.getInt(ReminderHelper.REMINDERS_METHOD_INDEX);
                switch (minutes) {
                    case 10:
                        assertEquals(Reminders.METHOD_DEFAULT, method);
                        break;
                    case 15:
                        assertEquals(Reminders.METHOD_ALERT, method);
                        break;
                    case 20:
                        assertEquals(Reminders.METHOD_SMS, method);
                        break;
                    default:
                        fail("unexpected minutes " + minutes);
                        break;
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        /*
         * Use the bulk update feature to change all METHOD_DEFAULT to METHOD_EMAIL.  To make
         * this more interesting we first change remId3 to METHOD_DEFAULT.
         */
        int count;
        ContentValues newValues = new ContentValues();
        newValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        count = mContentResolver.update(ContentUris.withAppendedId(Reminders.CONTENT_URI, remId3),
                newValues, null, null);
        assertEquals(1, count);

        newValues.put(Reminders.METHOD, Reminders.METHOD_EMAIL);
        count = mContentResolver.update(Reminders.CONTENT_URI, newValues,
                Reminders.EVENT_ID + "=? AND " + Reminders.METHOD + "=?",
                new String[] {
                    String.valueOf(eventId1), String.valueOf(Reminders.METHOD_DEFAULT)
                });
        assertEquals(2, count);

        // check it
        int method = ReminderHelper.lookupMethod(mContentResolver, remId3);
        assertEquals(Reminders.METHOD_EMAIL, method);

        /*
         * Delete some / all reminders and confirm that hasAlarm tracks it.
         *
         * You can also remove reminders from an event by updating the event_id column, but
         * that's defined as producing undefined behavior, so we don't do it here.
         */
        count = mContentResolver.delete(Reminders.CONTENT_URI,
                Reminders.EVENT_ID + "=? AND " + Reminders.MINUTES + ">=?",
                new String[] { String.valueOf(eventId1), "15" });
        assertEquals(2, count);
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId1);
        assertEquals(1, hasAlarm);

        // Delete all reminders from both events.
        count = mContentResolver.delete(Reminders.CONTENT_URI,
                Reminders.EVENT_ID + "=? OR " + Reminders.EVENT_ID + "=?",
                new String[] { String.valueOf(eventId1), String.valueOf(eventId2) });
        assertEquals(2, count);
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId1);
        assertEquals(0, hasAlarm);
        hasAlarm = EventHelper.lookupHasAlarm(mContentResolver, eventId2);
        assertEquals(0, hasAlarm);

        /*
         * Add a couple of reminders and then delete one with the by-ID URI.
         */
        long remId4 = ReminderHelper.addReminder(mContentResolver, eventId1,
                10, Reminders.METHOD_EMAIL);
        long remId5 = ReminderHelper.addReminder(mContentResolver, eventId1,
                15, Reminders.METHOD_EMAIL);
        count = mContentResolver.delete(ContentUris.withAppendedId(Reminders.CONTENT_URI, remId4),
                null, null);
        assertEquals(1, count);

        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * A listener for the EVENT_REMINDER broadcast that is expected to be fired by the
     * provider at the reminder time.
     */
    public class MockReminderReceiver extends BroadcastReceiver {
        public boolean received = false;

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action.equals(CalendarContract.ACTION_EVENT_REMINDER)) {
                received = true;
            }
        }
    }

    /**
     * Test that reminders result in the expected broadcast at reminder time.
     */
    public void testRemindersAlarm() throws Exception {
        // Setup: register a mock listener for the broadcast we expect to fire at the
        // reminder time.
        final MockReminderReceiver reminderReceiver = new MockReminderReceiver();
        IntentFilter filter = new IntentFilter(CalendarContract.ACTION_EVENT_REMINDER);
        filter.addDataScheme("content");
        getInstrumentation().getTargetContext().registerReceiver(reminderReceiver, filter);

        // Clean up just in case.
        String account = "rem_account";
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar.  Use '1' as seed as this sets the VISIBLE field to 1.
        // The calendar must be visible for its notifications to occur.
        long calendarId = createAndVerifyCalendar(account, 1, null);

        // Create event for 15 min in the past, with a 10 min reminder, so that it will
        // trigger immediately.
        ContentValues eventValues;
        int seed = 0;
        long now = System.currentTimeMillis();
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.DTSTART, now - DateUtils.MINUTE_IN_MILLIS * 15);
        eventValues.put(Events.DTEND, now + DateUtils.HOUR_IN_MILLIS);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId >= 0);
        ReminderHelper.addReminder(mContentResolver, eventId, 10, Reminders.METHOD_ALERT);

        // Confirm that the EVENT_REMINDER broadcast was fired by the provider.
        new PollingCheck(POLLING_TIMEOUT) {
            @Override
            protected boolean check() {
                return reminderReceiver.received;
            }
        }.run();
        assertTrue(reminderReceiver.received);

        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testColorWriteRequirements() {
        String account = "colw_account";
        String account2 = "colw2_account";
        int seed = 0;
        Uri uri = asSyncAdapter(Colors.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri uri2 = asSyncAdapter(Colors.CONTENT_URI, account2, CTS_TEST_TYPE);

        // Clean up just in case
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
        ColorHelper.deleteColorsByAccount(mContentResolver, account2, CTS_TEST_TYPE);

        ContentValues colorValues = new ContentValues();
        // Account name/type must be in the query params, so may be left
        // out here
        colorValues.put(Colors.DATA, "0");
        colorValues.put(Colors.COLOR_KEY, "1");
        colorValues.put(Colors.COLOR_TYPE, 0);
        colorValues.put(Colors.COLOR, 0xff000000);

        // Verify only a sync adapter can write to Colors
        try {
            mContentResolver.insert(Colors.CONTENT_URI, colorValues);
            fail("Should not allow non-sync adapter to insert colors");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Verify everything except DATA is required
        ContentValues testVals = new ContentValues(colorValues);
        for (String key : colorValues.keySet()) {

            testVals.remove(key);
            try {
                Uri colUri = mContentResolver.insert(uri, testVals);
                if (!TextUtils.equals(key, Colors.DATA)) {
                    // The DATA field is allowed to be empty.
                    fail("Should not allow color creation without " + key);
                }
                ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
            } catch (IllegalArgumentException e) {
                if (TextUtils.equals(key, Colors.DATA)) {
                    // The DATA field is allowed to be empty.
                    fail("Should allow color creation without " + key);
                }
            }
            testVals.put(key, colorValues.getAsString(key));
        }

        // Verify writing a color works
        Uri col1 = mContentResolver.insert(uri, colorValues);

        // Verify adding the same color fails
        try {
            mContentResolver.insert(uri, colorValues);
            fail("Should not allow adding the same color twice");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Verify specifying a different account than the query params doesn't work
        colorValues.put(Colors.ACCOUNT_NAME, account2);
        try {
            mContentResolver.insert(uri, colorValues);
            fail("Should use the account from the query params, not the values.");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Verify adding a color to a different account works
        Uri col2 = mContentResolver.insert(uri2, colorValues);

        // And a different index on the same account
        colorValues.put(Colors.COLOR_KEY, "2");
        Uri col3 = mContentResolver.insert(uri2, colorValues);

        // Verify that all three colors are in the table
        Cursor c = ColorHelper.findColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
        assertEquals(1, c.getCount());
        c.close();
        c = ColorHelper.findColorsByAccount(mContentResolver, account2, CTS_TEST_TYPE);
        assertEquals(2, c.getCount());
        c.close();

        // Verify deleting them works
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
        ColorHelper.deleteColorsByAccount(mContentResolver, account2, CTS_TEST_TYPE);

        c = ColorHelper.findColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
        assertEquals(0, c.getCount());
        c.close();
        c = ColorHelper.findColorsByAccount(mContentResolver, account2, CTS_TEST_TYPE);
        assertEquals(0, c.getCount());
        c.close();
    }

    /**
     * Tests Colors interaction with the Calendars table.
     */
    @MediumTest
    public void testCalendarColors() {
        String account = "cc_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);

        // Test inserting a calendar with an invalid color index
        ContentValues cv = CalendarHelper.getNewCalendarValues(account, seed++);
        cv.put(Calendars.CALENDAR_COLOR_KEY, "badIndex");
        Uri calSyncUri = asSyncAdapter(Calendars.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri colSyncUri = asSyncAdapter(Colors.CONTENT_URI, account, CTS_TEST_TYPE);

        try {
            Uri uri = mContentResolver.insert(calSyncUri, cv);
            fail("Should not allow insertion of invalid color index into Calendars");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Test updating a calendar with an invalid color index
        long calendarId = createAndVerifyCalendar(account, seed++, null);
        cv.clear();
        cv.put(Calendars.CALENDAR_COLOR_KEY, "badIndex2");
        Uri calendarUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calendarId);
        try {
            mContentResolver.update(calendarUri, cv, null, null);
            fail("Should not allow update of invalid color index into Calendars");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        assertTrue(ColorHelper.addDefaultColorsToAccount(mContentResolver, account, CTS_TEST_TYPE));

        // Test that inserting a valid color index works
        cv = CalendarHelper.getNewCalendarValues(account, seed++);
        cv.put(Calendars.CALENDAR_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_0]);

        Uri uri = mContentResolver.insert(calSyncUri, cv);
        long calendarId2 = ContentUris.parseId(uri);
        assertTrue(calendarId2 >= 0);
        // And updates the calendar's color to the one in the table
        cv.put(Calendars.CALENDAR_COLOR, ColorHelper.DEFAULT_COLORS[ColorHelper.C_COLOR_0]);
        verifyCalendar(account, cv, calendarId2, 2);

        // Test that updating a valid color index also updates the color in a
        // calendar
        cv.clear();
        cv.put(Calendars.CALENDAR_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_0]);
        mContentResolver.update(calendarUri, cv, null, null);
        Cursor c = mContentResolver.query(calendarUri,
                new String[] { Calendars.CALENDAR_COLOR_KEY, Calendars.CALENDAR_COLOR },
                null, null, null);
        try {
            c.moveToFirst();
            String index = c.getString(0);
            int color = c.getInt(1);
            assertEquals(index, ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_0]);
            assertEquals(color, ColorHelper.DEFAULT_COLORS[ColorHelper.C_COLOR_0]);
        } finally {
            if (c != null) {
                c.close();
            }
        }

        // And clearing it doesn't change the color
        cv.put(Calendars.CALENDAR_COLOR_KEY, (String) null);
        mContentResolver.update(calendarUri, cv, null, null);
        c = mContentResolver.query(calendarUri,
                new String[] { Calendars.CALENDAR_COLOR_KEY, Calendars.CALENDAR_COLOR },
                null, null, null);
        try {
            c.moveToFirst();
            String index = c.getString(0);
            int color = c.getInt(1);
            assertEquals(index, null);
            assertEquals(ColorHelper.DEFAULT_COLORS[ColorHelper.C_COLOR_0], color);
        } finally {
            if (c != null) {
                c.close();
            }
        }

        // Test that setting a calendar color to an event color fails
        cv.put(Calendars.CALENDAR_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_0]);
        try {
            mContentResolver.update(calendarUri, cv, null, null);
            fail("Should not allow a calendar to use an event color");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Test that you can't remove a color that is referenced by a calendar
        cv.put(Calendars.CALENDAR_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_3]);
        mContentResolver.update(calendarUri, cv, null, null);

        try {
            mContentResolver.delete(colSyncUri, ColorHelper.WHERE_COLOR_ACCOUNT_AND_INDEX,
                    new String[] {
                            account, CTS_TEST_TYPE,
                            ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_3]
                    });
            fail("Should not allow deleting referenced color");
        } catch (UnsupportedOperationException e) {
            // WAI
        }

        // Clean up
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
    }

    /**
     * Tests Colors interaction with the Events table.
     */
    @MediumTest
    public void testEventColors() {
        String account = "ec_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);

        // Test inserting an event with an invalid color index
        long cal_id = createAndVerifyCalendar(account, seed++, null);

        Uri colSyncUri = asSyncAdapter(Colors.CONTENT_URI, account, CTS_TEST_TYPE);

        ContentValues ev = EventHelper.getNewEventValues(account, seed++, cal_id, false);
        ev.put(Events.EVENT_COLOR_KEY, "badIndex");

        try {
            Uri uri = mContentResolver.insert(Events.CONTENT_URI, ev);
            fail("Should not allow insertion of invalid color index into Events");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Test updating an event with an invalid color index fails
        long event_id = createAndVerifyEvent(account, seed++, cal_id, false, null);
        ev.clear();
        ev.put(Events.EVENT_COLOR_KEY, "badIndex2");
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, event_id);
        try {
            mContentResolver.update(eventUri, ev, null, null);
            fail("Should not allow update of invalid color index into Events");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        assertTrue(ColorHelper.addDefaultColorsToAccount(mContentResolver, account, CTS_TEST_TYPE));

        // Test that inserting a valid color index works
        ev = EventHelper.getNewEventValues(account, seed++, cal_id, false);
        final String defaultColorIndex = ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_0];
        ev.put(Events.EVENT_COLOR_KEY, defaultColorIndex);

        Uri uri = mContentResolver.insert(Events.CONTENT_URI, ev);
        long eventId2 = ContentUris.parseId(uri);
        assertTrue(eventId2 >= 0);
        // And updates the event's color to the one in the table
        final int expectedColor = ColorHelper.DEFAULT_COLORS[ColorHelper.E_COLOR_0];
        ev.put(Events.EVENT_COLOR, expectedColor);
        verifyEvent(ev, eventId2);

        // Test that event iterator has COLOR columns
        final EntityIterator iterator = EventsEntity.newEntityIterator(mContentResolver.query(
                ContentUris.withAppendedId(EventsEntity.CONTENT_URI, eventId2),
                null, null, null, null), mContentResolver);
        assertTrue("Empty Iterator", iterator.hasNext());
        final Entity entity = iterator.next();
        final ContentValues values = entity.getEntityValues();
        assertTrue("Missing EVENT_COLOR", values.containsKey(EventsEntity.EVENT_COLOR));
        assertEquals("Wrong EVENT_COLOR",
                expectedColor,
                (int) values.getAsInteger(EventsEntity.EVENT_COLOR));
        assertTrue("Missing EVENT_COLOR_KEY", values.containsKey(EventsEntity.EVENT_COLOR_KEY));
        assertEquals("Wrong EVENT_COLOR_KEY",
                defaultColorIndex,
                values.getAsString(EventsEntity.EVENT_COLOR_KEY));
        iterator.close();

        // Test that updating a valid color index also updates the color in an
        // event
        ev.clear();
        ev.put(Events.EVENT_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_1]);
        mContentResolver.update(eventUri, ev, null, null);
        Cursor c = mContentResolver.query(eventUri, new String[] {
                Events.EVENT_COLOR_KEY, Events.EVENT_COLOR
        }, null, null, null);
        try {
            c.moveToFirst();
            String index = c.getString(0);
            int color = c.getInt(1);
            assertEquals(index, ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_1]);
            assertEquals(color, ColorHelper.DEFAULT_COLORS[ColorHelper.E_COLOR_1]);
        } finally {
            if (c != null) {
                c.close();
            }
        }

        // And clearing it doesn't change the color
        ev.put(Events.EVENT_COLOR_KEY, (String) null);
        mContentResolver.update(eventUri, ev, null, null);
        c = mContentResolver.query(eventUri, new String[] {
                Events.EVENT_COLOR_KEY, Events.EVENT_COLOR
        }, null, null, null);
        try {
            c.moveToFirst();
            String index = c.getString(0);
            int color = c.getInt(1);
            assertEquals(index, null);
            assertEquals(ColorHelper.DEFAULT_COLORS[ColorHelper.E_COLOR_1], color);
        } finally {
            if (c != null) {
                c.close();
            }
        }

        // Test that setting an event color to a calendar color fails
        ev.put(Events.EVENT_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.C_COLOR_2]);
        try {
            mContentResolver.update(eventUri, ev, null, null);
            fail("Should not allow an event to use a calendar color");
        } catch (IllegalArgumentException e) {
            // WAI
        }

        // Test that you can't remove a color that is referenced by an event
        ev.put(Events.EVENT_COLOR_KEY, ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_1]);
        mContentResolver.update(eventUri, ev, null, null);
        try {
            mContentResolver.delete(colSyncUri, ColorHelper.WHERE_COLOR_ACCOUNT_AND_INDEX,
                    new String[] {
                            account, CTS_TEST_TYPE,
                            ColorHelper.DEFAULT_INDICES[ColorHelper.E_COLOR_1]
                    });
            fail("Should not allow deleting referenced color");
        } catch (UnsupportedOperationException e) {
            // WAI
        }

        // TODO test colors with exceptions

        // Clean up
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        ColorHelper.deleteColorsByAccount(mContentResolver, account, CTS_TEST_TYPE);
    }

    /**
     * Tests creation and manipulation of ExtendedProperties.
     */
    @MediumTest
    public void testExtendedProperties() {
        String account = "ep_account";
        int seed = 0;

        // Clean up just in case.
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar.
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create events.
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId1 >= 0);

        /*
         * Add some extended properties.
         */
        long epId1 = ExtendedPropertiesHelper.addExtendedProperty(mContentResolver, account,
                eventId1, "first", "Jeffrey");
        long epId2 = ExtendedPropertiesHelper.addExtendedProperty(mContentResolver, account,
                eventId1, "last", "Lebowski");
        long epId3 = ExtendedPropertiesHelper.addExtendedProperty(mContentResolver, account,
                eventId1, "title", "Dude");

        /*
         * Spot-check a couple of entries.
         */
        Cursor cursor = ExtendedPropertiesHelper.findExtendedPropertiesByEventId(mContentResolver,
                eventId1);
        try {
            assertEquals(3, cursor.getCount());
            //DatabaseUtils.dumpCursor(cursor);

            while (cursor.moveToNext()) {
                String name =
                    cursor.getString(ExtendedPropertiesHelper.EXTENDED_PROPERTIES_NAME_INDEX);
                String value =
                    cursor.getString(ExtendedPropertiesHelper.EXTENDED_PROPERTIES_VALUE_INDEX);

                if (name.equals("last")) {
                    assertEquals("Lebowski", value);
                }
            }

            String title = ExtendedPropertiesHelper.lookupValueByName(mContentResolver, eventId1,
                    "title");
            assertEquals("Dude", title);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        // Update the title.  Must be done as a sync adapter.
        ContentValues newValues = new ContentValues();
        newValues.put(ExtendedProperties.VALUE, "Big");
        Uri uri = ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, epId3);
        uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        int count = mContentResolver.update(uri, newValues, null, null);
        assertEquals(1, count);

        // check it
        String title = ExtendedPropertiesHelper.lookupValueByName(mContentResolver, eventId1,
                "title");
        assertEquals("Big", title);

        removeAndVerifyCalendar(account, calendarId);
    }

    private class CalendarEventHelper {

      private long mCalendarId;
      private String mAccount;
      private int mSeed;

      public CalendarEventHelper(String account, int seed) {
        mAccount = account;
        mSeed = seed;
        ContentValues values = CalendarHelper.getNewCalendarValues(account, seed);
        mCalendarId = createAndVerifyCalendar(account, seed++, values);
      }

      public ContentValues addEvent(String timeString, int timeZoneIndex, long duration) {
        long event1Start = timeInMillis(timeString, timeZoneIndex);
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(mAccount, mSeed++, mCalendarId, true);
        eventValues.put(Events.DESCRIPTION, timeString);
        eventValues.put(Events.DTSTART, event1Start);
        eventValues.put(Events.DTEND, event1Start + duration);
        eventValues.put(Events.EVENT_TIMEZONE, TIME_ZONES[timeZoneIndex]);
        long eventId = createAndVerifyEvent(mAccount, mSeed, mCalendarId, true, eventValues);
        assertTrue(eventId >= 0);
        return eventValues;
      }

      public long getCalendarId() {
        return mCalendarId;
      }
    }

    /**
     * Test query to retrieve instances within a certain time interval.
     */
    public void testWhenByDayQuery() {
      String account = "cser_account";
      int seed = 0;

      // Clean up just in case
      CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

      // Create a calendar
      CalendarEventHelper helper = new CalendarEventHelper(account, seed);

      // Add events to the calendar--the first two in the queried range
      List<ContentValues> eventsWithinRange = new ArrayList<ContentValues>();

      ContentValues values = helper.addEvent("2009-10-01T08:00:00", 0, DateUtils.HOUR_IN_MILLIS);
      eventsWithinRange.add(values);

      values = helper.addEvent("2010-10-01T08:00:00", 0, DateUtils.HOUR_IN_MILLIS);
      eventsWithinRange.add(values);

      helper.addEvent("2011-10-01T08:00:00", 0, DateUtils.HOUR_IN_MILLIS);

      // Prepare the start time and end time of the range to query
      String startTime = "2009-01-01T00:00:00";
      String endTime = "2011-01-01T00:00:00";
      int julianStart = getJulianDay(startTime, 0);
      int julianEnd = getJulianDay(endTime, 0);
      Uri uri = Uri.withAppendedPath(
          CalendarContract.Instances.CONTENT_BY_DAY_URI, julianStart + "/" + julianEnd);

      // Query the range, sorting by event start time
      Cursor c = mContentResolver.query(uri, null, Instances.CALENDAR_ID + "="
              + helper.getCalendarId(), null, Events.DTSTART);

      // Assert that two events are returned
      assertEquals(c.getCount(), 2);

      Set<String> keySet = new HashSet();
      keySet.add(Events.DESCRIPTION);
      keySet.add(Events.DTSTART);
      keySet.add(Events.DTEND);
      keySet.add(Events.EVENT_TIMEZONE);

      // Verify that the contents of those two events match the cursor results
      verifyContentValuesAgainstCursor(eventsWithinRange, keySet, c);
    }

    private void verifyContentValuesAgainstCursor(List<ContentValues> cvs,
        Set<String> keys, Cursor cursor) {
      assertEquals(cursor.getCount(), cvs.size());

      cursor.moveToFirst();

      int i=0;
      do {
        ContentValues cv = cvs.get(i);
        for (String key : keys) {
          assertEquals(cv.get(key).toString(),
                  cursor.getString(cursor.getColumnIndex(key)));
        }
        i++;
      } while (cursor.moveToNext());

      cursor.close();
    }

    private long timeInMillis(String timeString, int timeZoneIndex) {
      Time startTime = new Time(TIME_ZONES[timeZoneIndex]);
      startTime.parse3339(timeString);
      return startTime.toMillis(false);
    }

    private int getJulianDay(String timeString, int timeZoneIndex) {
      Time time = new Time(TIME_ZONES[timeZoneIndex]);
      time.parse3339(timeString);
      return Time.getJulianDay(time.toMillis(false), time.gmtoff);
    }

    /**
     * Test instance queries with search parameters.
     */
    @MediumTest
    public void testInstanceSearch() {
        String account = "cser_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create a calendar
        ContentValues values = CalendarHelper.getNewCalendarValues(account, seed);
        long calendarId = createAndVerifyCalendar(account, seed++, values);

        String testStart = "2009-10-01T08:00:00";
        String timeZone = TIME_ZONES[0];
        Time startTime = new Time(timeZone);
        startTime.parse3339(testStart);
        long startMillis = startTime.toMillis(false);

        // Create some events, with different descriptions.  (Could also create a single
        // recurring event and some instance exceptions.)
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.DESCRIPTION, "testevent event-one fiddle");
        eventValues.put(Events.DTSTART, startMillis);
        eventValues.put(Events.DTEND, startMillis + DateUtils.HOUR_IN_MILLIS);
        eventValues.put(Events.EVENT_TIMEZONE, timeZone);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId1 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.DESCRIPTION, "testevent event-two fuzzle");
        eventValues.put(Events.DTSTART, startMillis + DateUtils.HOUR_IN_MILLIS);
        eventValues.put(Events.DTEND, startMillis + DateUtils.HOUR_IN_MILLIS * 2);
        eventValues.put(Events.EVENT_TIMEZONE, timeZone);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId2 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.DESCRIPTION, "testevent event-three fiddle");
        eventValues.put(Events.DTSTART, startMillis + DateUtils.HOUR_IN_MILLIS * 2);
        eventValues.put(Events.DTEND, startMillis + DateUtils.HOUR_IN_MILLIS * 3);
        eventValues.put(Events.EVENT_TIMEZONE, timeZone);
        long eventId3 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId3 >= 0);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        eventValues.put(Events.DESCRIPTION, "nontestevent");
        eventValues.put(Events.DTSTART, startMillis + (long) (DateUtils.HOUR_IN_MILLIS * 1.5f));
        eventValues.put(Events.DTEND, startMillis + DateUtils.HOUR_IN_MILLIS * 2);
        eventValues.put(Events.EVENT_TIMEZONE, timeZone);
        long eventId4 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId4 >= 0);

        String rangeStart = "2009-10-01T00:00:00";
        String rangeEnd = "2009-10-01T11:59:59";
        String[] projection = new String[] { Instances.BEGIN };

        if (false) {
            Cursor instances = getInstances(timeZone, rangeStart, rangeEnd, projection,
                    new long[] { calendarId });
            dumpInstances(instances, timeZone, "all");
            instances.close();
        }

        Cursor instances;
        int count;

        // Find all matching "testevent".  The search matches on partial strings, so this
        // will also pick up "nontestevent".
        instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
                "testevent", false, projection, new long[] { calendarId });
        count = instances.getCount();
        instances.close();
        assertEquals(4, count);

        // Find all matching "fiddle" and "event".  Set the "by day" flag just to be different.
        instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
                "fiddle event", true, projection, new long[] { calendarId });
        count = instances.getCount();
        instances.close();
        assertEquals(2, count);

        // Find all matching "fiddle" and "baluchitherium".
        instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
                "baluchitherium fiddle", false, projection, new long[] { calendarId });
        count = instances.getCount();
        instances.close();
        assertEquals(0, count);

        // Find all matching "event-two".
        instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
                "event-two", false, projection, new long[] { calendarId });
        count = instances.getCount();
        instances.close();
        assertEquals(1, count);

        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testCalendarUpdateAsApp() {
        String account = "cu1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create a calendar
        ContentValues values = CalendarHelper.getNewCalendarValues(account, seed);
        long id = createAndVerifyCalendar(account, seed++, values);

        Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, id);

        // Update the calendar using the direct Uri
        ContentValues updateValues = CalendarHelper.getUpdateCalendarValuesWithOriginal(
                values, seed++);
        assertEquals(1, mContentResolver.update(uri, updateValues, null, null));

        verifyCalendar(account, values, id, 1);

        // Update the calendar using selection + args
        String selection = Calendars._ID + "=?";
        String[] selectionArgs = new String[] { Long.toString(id) };

        updateValues = CalendarHelper.getUpdateCalendarValuesWithOriginal(values, seed++);

        assertEquals(1, mContentResolver.update(
                Calendars.CONTENT_URI, updateValues, selection, selectionArgs));

        verifyCalendar(account, values, id, 1);

        removeAndVerifyCalendar(account, id);
    }

    // TODO test calendar updates as sync adapter

    /**
     * Test access to the "syncstate" table.
     */
    @MediumTest
    public void testSyncState() {
        String account = "ss_account";
        int seed = 0;

        // Clean up just in case
        SyncStateHelper.deleteSyncStateByAccount(mContentResolver, account, true);

        // Create a new sync state entry
        ContentValues values = SyncStateHelper.getNewSyncStateValues(account);
        long id = createAndVerifySyncState(account, values);

        // Look it up with the by-ID URI
        Cursor c = SyncStateHelper.getSyncStateById(mContentResolver, id);
        assertNotNull(c);
        assertEquals(1, c.getCount());
        c.close();

        // Try to remove it as non-sync-adapter; expected to fail.
        boolean failed;
        try {
            SyncStateHelper.deleteSyncStateByAccount(mContentResolver, account, false);
            failed = false;
        } catch (IllegalArgumentException iae) {
            failed = true;
        }
        assertTrue("deletion of sync state by app was allowed", failed);

        // Remove it and verify that it's gone
        removeAndVerifySyncState(account);
    }


    private void verifyEvent(ContentValues values, long eventId) {
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        // Verify
        Cursor c = mContentResolver
                .query(eventUri, EventHelper.EVENTS_PROJECTION, null, null, null);
        assertEquals(1, c.getCount());
        assertTrue(c.moveToFirst());
        assertEquals(eventId, c.getLong(0));
        for (String key : values.keySet()) {
            int index = c.getColumnIndex(key);
            assertEquals(key, values.getAsString(key), c.getString(index));
        }
        c.close();
    }

    @MediumTest
    public void testEventCreationAndDeletion() {
        String account = "ec1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar and event
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        removeAndVerifyEvent(eventUri, eventValues, account);

        // Attempt to create an event without a calendar ID.
        ContentValues badValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        badValues.remove(Events.CALENDAR_ID);
        try {
            createAndVerifyEvent(account, seed, calendarId, true, badValues);
            fail("was allowed to create an event without CALENDAR_ID");
        } catch (IllegalArgumentException iae) {
            // expected
        }

        // Validation may be relaxed for content providers, so test missing timezone as app.
        badValues = EventHelper.getNewEventValues(account, seed++, calendarId, false);
        badValues.remove(Events.EVENT_TIMEZONE);
        try {
            createAndVerifyEvent(account, seed, calendarId, false, badValues);
            fail("was allowed to create an event without EVENT_TIMEZONE");
        } catch (IllegalArgumentException iae) {
            // expected
        }

        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testEventUpdateAsApp() {
        String account = "em1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create event as sync adapter
        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        // Update event as app
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        ContentValues updateValues = EventHelper.getUpdateEventValuesWithOriginal(eventValues,
                seed++, false);
        assertEquals(1, mContentResolver.update(eventUri, updateValues, null, null));
        updateValues.put(Events.DIRTY, 1);      // provider should have marked as dirty
        verifyEvent(updateValues, eventId);

        // Try nulling out a required value.
        ContentValues badValues = new ContentValues(updateValues);
        badValues.putNull(Events.EVENT_TIMEZONE);
        badValues.remove(Events.DIRTY);
        try {
            mContentResolver.update(eventUri, badValues, null, null);
            fail("was allowed to null out EVENT_TIMEZONE");
        } catch (IllegalArgumentException iae) {
            // good
        }

        removeAndVerifyEvent(eventUri, eventValues, account);

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests update of multiple events with a single update call.
     */
    @MediumTest
    public void testBulkUpdate() {
        String account = "bup_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);
        String calendarIdStr = String.valueOf(calendarId);

        // Create events
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        // Update the "description" field in all events in this calendar.
        String newDescription = "bulk edit";
        ContentValues updateValues = new ContentValues();
        updateValues.put(Events.DESCRIPTION, newDescription);

        // Must be sync adapter to do a bulk update.
        Uri uri = asSyncAdapter(Events.CONTENT_URI, account, CTS_TEST_TYPE);
        int count = mContentResolver.update(uri, updateValues, SQL_WHERE_CALENDAR_ID,
                new String[] { calendarIdStr });

        // Check to see if the changes went through.
        Uri eventUri = Events.CONTENT_URI;
        Cursor c = mContentResolver.query(eventUri, new String[] { Events.DESCRIPTION },
                SQL_WHERE_CALENDAR_ID, new String[] { calendarIdStr }, null);
        assertEquals(2, c.getCount());
        while (c.moveToNext()) {
            assertEquals(newDescription, c.getString(0));
        }
        c.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests the content provider's enforcement of restrictions on who is allowed to modify
     * specific columns in a Calendar.
     * <p>
     * This attempts to create a new row in the Calendar table, specifying one restricted
     * column at a time.
     */
    @MediumTest
    public void testSyncOnlyInsertEnforcement() {
        // These operations should not succeed, so there should be nothing to clean up after.
        // TODO: this should be a new event augmented with an illegal column, not a single
        //       column.  Otherwise we might be tripping over a "DTSTART must exist" test.
        ContentValues vals = new ContentValues();
        for (int i = 0; i < Calendars.SYNC_WRITABLE_COLUMNS.length; i++) {
            boolean threw = false;
            try {
                vals.clear();
                vals.put(Calendars.SYNC_WRITABLE_COLUMNS[i], "1");
                mContentResolver.insert(Calendars.CONTENT_URI, vals);
            } catch (IllegalArgumentException e) {
                threw = true;
            }
            assertTrue("Only sync adapter should be allowed to insert "
                    + Calendars.SYNC_WRITABLE_COLUMNS[i], threw);
        }
    }

    /**
     * Tests creation of a recurring event.
     * <p>
     * This (and the other recurrence tests) uses dates well in the past to reduce the likelihood
     * of encountering non-test recurring events.  (Ideally we would select events associated
     * with a specific calendar.)  With dates well in the past, it's also important to have a
     * fixed maximum count or end date; otherwise, if the metadata min/max instance values are
     * large enough, the recurrence recalculation processor could get triggered on an insert or
     * update and bump up against the 2000-instance limit.
     *
     * TODO: need some allDay tests
     */
    @MediumTest
    public void testRecurrence() {
        String account = "re_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "2003-08-05T09:00:00", "PT1H",
                "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU");
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        //Log.d(TAG, "+++ basic recurrence eventId is " + eventId);

        // Check to see if we have the expected number of instances
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        int instanceCount = getInstanceCount(timeZone, "2003-08-05T00:00:00",
                "2003-08-31T11:59:59", new long[] { calendarId });
        if (false) {
            Cursor instances = getInstances(timeZone, "2003-08-05T00:00:00", "2003-08-31T11:59:59",
                    new String[] { Instances.BEGIN }, new long[] { calendarId });
            dumpInstances(instances, timeZone, "initial");
            instances.close();
        }
        assertEquals("recurrence instance count", 4, instanceCount);

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests conversion of a regular event to a recurring event.
     */
    @MediumTest
    public void testConversionToRecurring() {
        String account = "reconv_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar and event
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        long dtstart = eventValues.getAsLong(Events.DTSTART);
        long dtend = eventValues.getAsLong(Events.DTEND);
        long durationSecs = (dtend - dtstart) / 1000;

        ContentValues updateValues = new ContentValues();
        updateValues.put(Events.RRULE, "FREQ=WEEKLY");   // recurs forever
        updateValues.put(Events.DURATION, "P" + durationSecs + "S");
        updateValues.putNull(Events.DTEND);

        // Issue update; do it as app instead of sync adapter to exercise that path.
        updateAndVerifyEvent(account, calendarId, eventId, false, updateValues);

        // Make sure LAST_DATE got nulled out by our infinitely repeating sequence.
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        Cursor c = mContentResolver.query(eventUri, new String[] { Events.LAST_DATE },
                null, null, null);
        assertEquals(1, c.getCount());
        assertTrue(c.moveToFirst());
        assertNull(c.getString(0));
        c.close();

        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation of a recurring event with single-instance exceptions.
     */
    @MediumTest
    public void testSingleRecurrenceExceptions() {
        String account = "rex_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event.
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1999-03-28T09:00:00", "PT1H", "FREQ=WEEKLY;WKST=SU;COUNT=100");
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // Add some attendees and reminders.
        addAttendees(account, eventId, seed);
        addReminders(account, eventId, seed);

        // Select a period that gives us 5 instances.  We don't want this to straddle a DST
        // transition, because we expect the startMinute field to be the same for all
        // instances, and it's stored as minutes since midnight in the device's time zone.
        // Things won't be consistent if the event and the device have different ideas about DST.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1999-07-02T00:00:00";
        String testEnd = "1999-08-04T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE, Instances.END_MINUTE };

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        /*
         * Advance the start time of a few instances, and verify.
         */

        // Leave first instance alone.
        instances.moveToPosition(1);

        long startMillis;
        ContentValues excepValues;

        // Advance the start time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        long excepEventId2 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the start time of the 3rd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000*2);
        long excepEventId3 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Cancel the 4th instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.STATUS, Events.STATUS_CANCELED);
        long excepEventId4 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // TODO: try to modify a non-existent instance.

        instances.close();

        // TODO: compare Reminders, Attendees, ExtendedProperties on one of the exception events

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with DTSTART exceptions");
        }
        assertEquals("exceptional recurrence instance count", 4, instances.getCount());

        long prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be different from the previous entry
            long startMinute = instances.getLong(1);
            assertTrue("instance start times are different", startMinute != prevMinute);

            prevMinute = startMinute;
        }
        instances.close();


        // Delete all of our exceptions, and verify.
        int deleteCount = 0;
        deleteCount += deleteException(account, eventId, excepEventId2);
        deleteCount += deleteException(account, eventId, excepEventId3);
        deleteCount += deleteException(account, eventId, excepEventId4);
        assertEquals("events deleted", 3, deleteCount);

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "post exception deletion");
        }
        assertEquals("post-exception deletion instance count", 5, instances.getCount());

        prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be the same
            long startMinute = instances.getLong(1);
            if (prevMinute != -1) {
                assertEquals("instance start times are the same", startMinute, prevMinute);
            }
            prevMinute = startMinute;
        }
        instances.close();

        /*
         * Repeat the test, this time modifying DURATION.
         */

        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        // Leave first instance alone.
        instances.moveToPosition(1);

        // Advance the end time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DURATION, "P" + 3600*2 + "S");
        excepEventId2 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the end time of the 3rd instance, and change the self-attendee status.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DURATION, "P" + 3600*3 + "S");
        excepValues.put(Events.SELF_ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED);
        excepEventId3 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the start time of the 4th instance, which will also advance the end time.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        excepEventId4 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        instances.close();

        // TODO: make sure the selfAttendeeStatus change took

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with DURATION exceptions");
        }
        assertEquals("exceptional recurrence instance count", 5, instances.getCount());

        prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be different from the previous entry
            long endMinute = instances.getLong(2);
            assertTrue("instance end times are different", endMinute != prevMinute);

            prevMinute = endMinute;
        }
        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation of a simple recurrence exception when not pretending to be the sync
     * adapter.  One significant consequence is that we don't set the _sync_id field in the
     * events, which affects how the provider correlates recurrences and exceptions.
     */
    @MediumTest
    public void testNonAdapterRecurrenceExceptions() {
        String account = "rena_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Generate recurring event, with "asSyncAdapter" set to false.
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, false, "1991-02-03T12:00:00", "PT1H", "FREQ=DAILY;WKST=SU;COUNT=10");

        // Select a period that gives us 3 instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1991-02-03T00:00:00";
        String testEnd = "1991-02-05T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };

        // Expand the bounds of the instances table so we expand future events as they are added.
        expandInstanceRange(account, calendarId, testStart, testEnd, timeZone);

        // Create the event in the database.
        long eventId = createAndVerifyEvent(account, seed++, calendarId, false, eventValues);
        assertTrue(eventId >= 0);

        // Add some attendees.
        addAttendees(account, eventId, seed);

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }
        assertEquals("initial recurrence instance count", 3, instances.getCount());

        /*
         * Alter the attendee status of the second event.  This should cause the instances to
         * be updated, replacing the previous 2nd instance with the exception instance.  If the
         * code is broken we'll see four instances (because the original instance didn't get
         * removed) or one instance (because the code correctly deleted all related events but
         * couldn't correlate the exception with its original recurrence).
         */

        // Leave first instance alone.
        instances.moveToPosition(1);

        long startMillis;
        ContentValues excepValues;

        // Advance the start time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.SELF_ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED);
        long excepEventId2 = createAndVerifyException(account, eventId, excepValues, false);
        instances.moveToNext();

        instances.close();

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with exceptions");
        }

        // TODO: this test currently fails due to limitations in the provider
        //assertEquals("exceptional recurrence instance count", 3, instances.getCount());

        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests insertion of event exceptions before and after a recurring event is created.
     * <p>
     * The server may send exceptions down before the event they refer to, so the provider
     * fills in the originalId of previously-existing exceptions when a recurring event is
     * inserted.  Make sure that works.
     * <p>
     * The _sync_id column is only unique with a given calendar.  We create events with
     * identical originalSyncId values in two different calendars to verify that the provider
     * doesn't update unrelated events.
     * <p>
     * We can't use the /exception URI, because that only works if the events are created
     * in order.
     */
    @MediumTest
    public void testOutOfOrderRecurrenceExceptions() {
        String account1 = "roid1_account";
        String account2 = "roid2_account";
        String startWhen = "1987-08-09T12:00:00";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account1);
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account2);

        // Create calendars
        long calendarId1 = createAndVerifyCalendar(account1, seed++, null);
        long calendarId2 = createAndVerifyCalendar(account2, seed++, null);


        // Generate base event.
        ContentValues recurEventValues = EventHelper.getNewRecurringEventValues(account1, seed++,
                calendarId1, true, startWhen, "PT1H", "FREQ=DAILY;WKST=SU;COUNT=10");

        // Select a period that gives us 3 instances.
        String timeZone = recurEventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1987-08-09T00:00:00";
        String testEnd = "1987-08-11T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE, Instances.EVENT_ID };

        /*
         * We're interested in exploring what the instance expansion code does with the events
         * as they arrive.  It won't do anything at event-creation time unless the instance
         * range already covers the interesting set of dates, so we need to create and remove
         * an instance in the same time frame beforehand.
         */
        expandInstanceRange(account1, calendarId1, testStart, testEnd, timeZone);

        /*
         * Instances table should be expanded.  Do the test.
         */

        final String MAGIC_SYNC_ID = "MagicSyncId";
        recurEventValues.put(Events._SYNC_ID, MAGIC_SYNC_ID);

        // Generate exceptions from base, removing the generated _sync_id and setting the
        // base event's _sync_id as originalSyncId.
        ContentValues beforeExcepValues, afterExcepValues, unrelatedExcepValues;
        beforeExcepValues = new ContentValues(recurEventValues);
        afterExcepValues = new ContentValues(recurEventValues);
        unrelatedExcepValues = new ContentValues(recurEventValues);
        beforeExcepValues.remove(Events._SYNC_ID);
        afterExcepValues.remove(Events._SYNC_ID);
        unrelatedExcepValues.remove(Events._SYNC_ID);
        beforeExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);
        afterExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);
        unrelatedExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);

        // Disassociate the "unrelated" exception by moving it to the other calendar.
        unrelatedExcepValues.put(Events.CALENDAR_ID, calendarId2);

        // We shift the start time by half an hour, and use the same _sync_id.
        final long ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
        final long ONE_HOUR_MILLIS  = 60 * 60 * 1000;
        final long HALF_HOUR_MILLIS  = 30 * 60 * 1000;
        long dtstartMillis = recurEventValues.getAsLong(Events.DTSTART) + ONE_DAY_MILLIS;
        beforeExcepValues.put(Events.ORIGINAL_INSTANCE_TIME, dtstartMillis);
        beforeExcepValues.put(Events.DTSTART, dtstartMillis + HALF_HOUR_MILLIS);
        beforeExcepValues.put(Events.DTEND, dtstartMillis + ONE_HOUR_MILLIS);
        beforeExcepValues.remove(Events.DURATION);
        beforeExcepValues.remove(Events.RRULE);
        beforeExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);
        dtstartMillis += ONE_DAY_MILLIS;
        afterExcepValues.put(Events.ORIGINAL_INSTANCE_TIME, dtstartMillis);
        afterExcepValues.put(Events.DTSTART, dtstartMillis + HALF_HOUR_MILLIS);
        afterExcepValues.put(Events.DTEND, dtstartMillis + ONE_HOUR_MILLIS);
        afterExcepValues.remove(Events.DURATION);
        afterExcepValues.remove(Events.RRULE);
        afterExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);
        dtstartMillis += ONE_DAY_MILLIS;
        unrelatedExcepValues.put(Events.ORIGINAL_INSTANCE_TIME, dtstartMillis);
        unrelatedExcepValues.put(Events.DTSTART, dtstartMillis + HALF_HOUR_MILLIS);
        unrelatedExcepValues.put(Events.DTEND, dtstartMillis + ONE_HOUR_MILLIS);
        unrelatedExcepValues.remove(Events.DURATION);
        unrelatedExcepValues.remove(Events.RRULE);
        unrelatedExcepValues.put(Events.ORIGINAL_SYNC_ID, MAGIC_SYNC_ID);


        // Create "before" and "unrelated" exceptions.
        long beforeEventId = createAndVerifyEvent(account1, seed, calendarId1, true,
                beforeExcepValues);
        assertTrue(beforeEventId >= 0);
        long unrelatedEventId = createAndVerifyEvent(account2, seed, calendarId2, true,
                unrelatedExcepValues);
        assertTrue(unrelatedEventId >= 0);

        // Create recurring event.
        long recurEventId = createAndVerifyEvent(account1, seed, calendarId1, true,
                recurEventValues);
        assertTrue(recurEventId >= 0);

        // Create "after" exception.
        long afterEventId = createAndVerifyEvent(account1, seed, calendarId1, true,
                afterExcepValues);
        assertTrue(afterEventId >= 0);

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "before=" + beforeEventId + ", unrel=" + unrelatedEventId +
                    ", recur=" + recurEventId + ", after=" + afterEventId);
        }

        // Check to see how many instances we get.  If the recurrence and the exception don't
        // get paired up correctly, we'll see too many instances.
        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId1, calendarId2 });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with exception");
        }

        assertEquals("initial recurrence instance count", 3, instances.getCount());

        instances.close();


        /*
         * Now we want to verify that:
         * - "before" and "after" have an originalId equal to our recurEventId
         * - "unrelated" has no originalId
         */
        Cursor c = null;
        try {
            final String[] PROJECTION = new String[] { Events.ORIGINAL_ID };
            Uri eventUri;
            Long originalId;

            eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, beforeEventId);
            c = mContentResolver.query(eventUri, PROJECTION, null, null, null);
            assertEquals(1, c.getCount());
            c.moveToNext();
            originalId = c.getLong(0);
            assertNotNull(originalId);
            assertEquals(recurEventId, (long) originalId);
            c.close();

            eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, afterEventId);
            c = mContentResolver.query(eventUri, PROJECTION, null, null, null);
            assertEquals(1, c.getCount());
            c.moveToNext();
            originalId = c.getLong(0);
            assertNotNull(originalId);
            assertEquals(recurEventId, (long) originalId);
            c.close();

            eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, unrelatedEventId);
            c = mContentResolver.query(eventUri, PROJECTION, null, null, null);
            assertEquals(1, c.getCount());
            c.moveToNext();
            assertNull(c.getString(0));
            c.close();

            c = null;
        } finally {
            if (c != null) {
                c.close();
            }
        }

        // delete the calendars
        removeAndVerifyCalendar(account1, calendarId1);
        removeAndVerifyCalendar(account2, calendarId2);
    }

    /**
     * Tests exceptions that modify all future instances of a recurring event.
     */
    @MediumTest
    public void testForwardRecurrenceExceptions() {
        String account = "refx_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1999-01-01T06:00:00", "PT1H", "FREQ=WEEKLY;WKST=SU;COUNT=10");
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // Add some attendees and reminders.
        addAttendees(account, eventId, seed++);
        addReminders(account, eventId, seed++);

        // Get some instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1999-01-01T00:00:00";
        String testEnd = "1999-01-29T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        // Modify starting from 3rd instance.
        instances.moveToPosition(2);

        long startMillis;
        ContentValues excepValues;

        // Replace with a new recurrence rule.  We move the start time an hour later, and cap
        // it at two instances.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        excepValues.put(Events.RRULE, "FREQ=WEEKLY;COUNT=2;WKST=SU");
        long excepEventId = createAndVerifyException(account, eventId, excepValues, true);
        instances.close();


        // Check to see if it took.
        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with new rule");
        }

        assertEquals("count with exception", 4, instances.getCount());

        long prevMinute = -1;
        for (int i = 0; i < 4; i++) {
            long startMinute;
            instances.moveToNext();
            switch (i) {
                case 0:
                    startMinute = instances.getLong(1);
                    break;
                case 1:
                case 3:
                    startMinute = instances.getLong(1);
                    assertEquals("first/last pairs match", prevMinute, startMinute);
                    break;
                case 2:
                    startMinute = instances.getLong(1);
                    assertFalse("first two != last two", prevMinute == startMinute);
                    break;
                default:
                    fail();
                    startMinute = -1;   // make compiler happy
                    break;
            }

            prevMinute = startMinute;
        }
        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests exceptions that modify all instances of a recurring event.  This is not really an
     * exception, since it won't create a new event, but supporting it allows us to use the
     * exception URI without having to determine whether the "start from here" instance is the
     * very first instance.
     */
    @MediumTest
    public void testFullRecurrenceUpdate() {
        String account = "ref_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=DAILY;WKST=MO;COUNT=100";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);
        //Log.i(TAG, "+++ eventId is " + eventId);

        // Get some instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1997-08-01T00:00:00";
        String testEnd = "1997-08-31T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.EVENT_LOCATION };
        String newLocation = "NEW!";

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 3, instances.getCount());

        instances.moveToFirst();
        long startMillis = instances.getLong(0);
        ContentValues excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.RRULE, rrule);   // identifies this as an "all future events" excep
        excepValues.put(Events.EVENT_LOCATION, newLocation);
        long excepEventId = createAndVerifyException(account, eventId, excepValues, true);
        instances.close();

        // Check results.
        assertEquals("full update does not create new ID", eventId, excepEventId);

        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        assertEquals("post-update instance count", 3, instances.getCount());
        while (instances.moveToNext()) {
            assertEquals("new location", newLocation, instances.getString(1));
        }
        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testMultiRuleRecurrence() {
        String account = "multirule_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=DAILY;WKST=MO;COUNT=5\nFREQ=WEEKLY;WKST=SU;COUNT=5";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // TODO: once multi-rule RRULEs are fully supported, verify that they work

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Issue bad requests and expect them to get rejected.
     */
    @MediumTest
    public void testBadRequests() {
        String account = "neg_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=OFTEN;WKST=MO";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        try {
            createAndVerifyEvent(account, seed++, calendarId, true, eventValues);
            fail("Bad recurrence rule should have been rejected");
        } catch (IllegalArgumentException iae) {
            // good
        }

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests correct behavior of Calendars.isPrimary column
     */
    @MediumTest
    public void testCalendarIsPrimary() {
        String account = "ec_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        int isPrimary;
        Cursor cursor;
        ContentValues values = new ContentValues();

        final long calendarId = createAndVerifyCalendar(account, seed++, null);
        final Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calendarId);

        // verify when ownerAccount != account_name && isPrimary IS NULL
        cursor = mContentResolver.query(uri, new String[]{Calendars.IS_PRIMARY}, null, null, null);
        cursor.moveToFirst();
        isPrimary = cursor.getInt(0);
        cursor.close();
        assertEquals("isPrimary should be 0 if ownerAccount != account_name", 0, isPrimary);

        // verify when ownerAccount == account_name && isPrimary IS NULL
        values.clear();
        values.put(Calendars.OWNER_ACCOUNT, account);
        mContentResolver.update(asSyncAdapter(uri, account, CTS_TEST_TYPE), values, null, null);
        cursor = mContentResolver.query(uri, new String[]{Calendars.IS_PRIMARY}, null, null, null);
        cursor.moveToFirst();
        isPrimary = cursor.getInt(0);
        cursor.close();
        assertEquals("isPrimary should be 1 if ownerAccount == account_name", 1, isPrimary);

        // verify isPrimary IS NOT NULL
        values.clear();
        values.put(Calendars.IS_PRIMARY, SOME_ARBITRARY_INT);
        mContentResolver.update(uri, values, null, null);
        cursor = mContentResolver.query(uri, new String[]{Calendars.IS_PRIMARY}, null, null, null);
        cursor.moveToFirst();
        isPrimary = cursor.getInt(0);
        cursor.close();
        assertEquals("isPrimary should be the value it was set to", SOME_ARBITRARY_INT, isPrimary);

        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
    }

    /**
     * Tests correct behavior of Events.isOrganizer column
     */
    @MediumTest
    public void testEventsIsOrganizer() {
        String account = "ec_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        int isOrganizer;
        Cursor cursor;
        ContentValues values = new ContentValues();

        final long calendarId = createAndVerifyCalendar(account, seed++, null);
        final long eventId = createAndVerifyEvent(account, seed, calendarId, true, null);
        final Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        // verify when ownerAccount != organizer && isOrganizer IS NULL
        cursor = mContentResolver.query(uri, new String[]{Events.IS_ORGANIZER}, null, null, null);
        cursor.moveToFirst();
        isOrganizer = cursor.getInt(0);
        cursor.close();
        assertEquals("isOrganizer should be 0 if ownerAccount != organizer", 0, isOrganizer);

        // verify when ownerAccount == account_name && isOrganizer IS NULL
        values.clear();
        values.put(Events.ORGANIZER, CalendarHelper.generateCalendarOwnerEmail(account));
        mContentResolver.update(asSyncAdapter(uri, account, CTS_TEST_TYPE), values, null, null);
        cursor = mContentResolver.query(uri, new String[]{Events.IS_ORGANIZER}, null, null, null);
        cursor.moveToFirst();
        isOrganizer = cursor.getInt(0);
        cursor.close();
        assertEquals("isOrganizer should be 1 if ownerAccount == organizer", 1, isOrganizer);

        // verify isOrganizer IS NOT NULL
        values.clear();
        values.put(Events.IS_ORGANIZER, SOME_ARBITRARY_INT);
        mContentResolver.update(uri, values, null, null);
        cursor = mContentResolver.query(uri, new String[]{Events.IS_ORGANIZER}, null, null, null);
        cursor.moveToFirst();
        isOrganizer = cursor.getInt(0);
        cursor.close();
        assertEquals(
                "isPrimary should be the value it was set to", SOME_ARBITRARY_INT, isOrganizer);
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
    }

    /**
     * Tests correct behavior of Events.uid2445 column
     */
    @MediumTest
    public void testEventsUid2445() {
        String account = "ec_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        final String uid = "uid_123";
        Cursor cursor;
        ContentValues values = new ContentValues();
        final long calendarId = createAndVerifyCalendar(account, seed++, null);
        final long eventId = createAndVerifyEvent(account, seed, calendarId, true, null);
        final Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        // Verify default is null
        cursor = mContentResolver.query(uri, new String[] {Events.UID_2445}, null, null, null);
        cursor.moveToFirst();
        assertTrue(cursor.isNull(0));
        cursor.close();

        // Write column value and read back
        values.clear();
        values.put(Events.UID_2445, uid);
        mContentResolver.update(asSyncAdapter(uri, account, CTS_TEST_TYPE), values, null, null);
        cursor = mContentResolver.query(uri, new String[] {Events.UID_2445}, null, null, null);
        cursor.moveToFirst();
        assertFalse(cursor.isNull(0));
        assertEquals("Column uid_2445 has unexpected value.", uid, cursor.getString(0));

        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
    }

    @MediumTest
    public void testMutatorSetCorrectly() {
        String account = "ec_account";
        String packageName = "android.provider.cts";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        String mutator;
        Cursor cursor;
        ContentValues values = new ContentValues();
        final long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Verify mutator is set to the package, via:
        // Create:
        final long eventId = createAndVerifyEvent(account, seed, calendarId, false, null);
        final Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        cursor = mContentResolver.query(uri, new String[] {Events.MUTATORS}, null, null, null);
        cursor.moveToFirst();
        mutator = cursor.getString(0);
        cursor.close();
        assertEquals(packageName, mutator);

        // Edit:
        // First clear the mutator column
        values.clear();
        values.putNull(Events.MUTATORS);
        mContentResolver.update(asSyncAdapter(uri, account, CTS_TEST_TYPE), values, null, null);
        cursor = mContentResolver.query(uri, new String[] {Events.MUTATORS}, null, null, null);
        cursor.moveToFirst();
        mutator = cursor.getString(0);
        cursor.close();
        assertNull(mutator);
        // Now edit the event and verify the mutator column
        values.clear();
        values.put(Events.TITLE, "New title");
        mContentResolver.update(uri, values, null, null);
        cursor = mContentResolver.query(uri, new String[] {Events.MUTATORS}, null, null, null);
        cursor.moveToFirst();
        mutator = cursor.getString(0);
        cursor.close();
        assertEquals(packageName, mutator);

        // Clean up the event
        assertEquals(1, EventHelper.deleteEventAsSyncAdapter(mContentResolver, uri, account));

        // Delete:
        // First create as sync adapter
        final long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, null);
        final Uri uri2 = ContentUris.withAppendedId(Events.CONTENT_URI, eventId2);
        // Now delete the event and verify
        values.clear();
        values.put(Events.MUTATORS, packageName);
        removeAndVerifyEvent(uri2, values, account);


        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Acquires the set of instances that appear between the specified start and end points.
     *
     * @param timeZone Time zone to use when parsing startWhen and endWhen
     * @param startWhen Start date/time, in RFC 3339 format
     * @param endWhen End date/time, in RFC 3339 format
     * @param projection Array of desired column names
     * @return Cursor with instances (caller should close when done)
     */
    private Cursor getInstances(String timeZone, String startWhen, String endWhen,
            String[] projection, long[] calendarIds) {
        Time startTime = new Time(timeZone);
        startTime.parse3339(startWhen);
        long startMillis = startTime.toMillis(false);

        Time endTime = new Time(timeZone);
        endTime.parse3339(endWhen);
        long endMillis = endTime.toMillis(false);

        // We want a list of instances that occur between the specified dates.  Use the
        // "instances/when" URI.
        Uri uri = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_URI,
                startMillis + "/" + endMillis);

        String where = null;
        for (int i = 0; i < calendarIds.length; i++) {
            if (i > 0) {
                where += " OR ";
            } else {
                where = "";
            }
            where += (Instances.CALENDAR_ID + "=" + calendarIds[i]);
        }
        Cursor instances = mContentResolver.query(uri, projection, where, null,
                projection[0] + " ASC");

        return instances;
    }

    /**
     * Acquires the set of instances that appear between the specified start and end points
     * that match the search terms.
     *
     * @param timeZone Time zone to use when parsing startWhen and endWhen
     * @param startWhen Start date/time, in RFC 3339 format
     * @param endWhen End date/time, in RFC 3339 format
     * @param search A collection of tokens to search for.  The columns searched are
     *   hard-coded in the provider (currently title, description, location, attendee
     *   name, attendee email).
     * @param searchByDay If set, adjust start/end to calendar day boundaries.
     * @param projection Array of desired column names
     * @return Cursor with instances (caller should close when done)
     */
    private Cursor getInstancesSearch(String timeZone, String startWhen, String endWhen,
            String search, boolean searchByDay, String[] projection, long[] calendarIds) {
        Time startTime = new Time(timeZone);
        startTime.parse3339(startWhen);
        long startMillis = startTime.toMillis(false);

        Time endTime = new Time(timeZone);
        endTime.parse3339(endWhen);
        long endMillis = endTime.toMillis(false);

        Uri uri;
        if (searchByDay) {
            // start/end are Julian day numbers rather than time in milliseconds
            int julianStart = Time.getJulianDay(startMillis, startTime.gmtoff);
            int julianEnd = Time.getJulianDay(endMillis, endTime.gmtoff);
            uri = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_SEARCH_BY_DAY_URI,
                    julianStart + "/" + julianEnd + "/" + search);
        } else {
            uri = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_SEARCH_URI,
                    startMillis + "/" + endMillis + "/" + search);
        }

        String where = null;
        for (int i = 0; i < calendarIds.length; i++) {
            if (i > 0) {
                where += " OR ";
            } else {
                where = "";
            }
            where += (Instances.CALENDAR_ID + "=" + calendarIds[i]);
        }
        // We want a list of instances that occur between the specified dates and that match
        // the search terms.

        Cursor instances = mContentResolver.query(uri, projection, where, null,
                projection[0] + " ASC");

        return instances;
    }

    /** debug -- dump instances cursor */
    private static void dumpInstances(Cursor instances, String timeZone, String msg) {
        Log.d(TAG, "Instances (" + msg + ")");

        int posn = instances.getPosition();
        instances.moveToPosition(-1);

        //Log.d(TAG, "+++ instances has " + instances.getCount() + " rows, " +
        //        instances.getColumnCount() + " columns");
        while (instances.moveToNext()) {
            long beginMil = instances.getLong(0);
            Time beginT = new Time(timeZone);
            beginT.set(beginMil);
            String logMsg = "--> begin=" + beginT.format3339(false) + " (" + beginMil + ")";
            for (int i = 2; i < instances.getColumnCount(); i++) {
                logMsg += " [" + instances.getString(i) + "]";
            }
            Log.d(TAG, logMsg);
        }
        instances.moveToPosition(posn);
    }


    /**
     * Counts the number of instances that appear between the specified start and end times.
     */
    private int getInstanceCount(String timeZone, String startWhen, String endWhen,
                long[] calendarIds) {
        Cursor instances = getInstances(timeZone, startWhen, endWhen,
                new String[] { Instances._ID }, calendarIds);
        int count = instances.getCount();
        instances.close();
        return count;
    }

    /**
     * Deletes an event as app and sync adapter which removes it from the db and
     * verifies after each.
     *
     * @param eventUri The uri for the event to delete
     * @param accountName TODO
     */
    private void removeAndVerifyEvent(Uri eventUri, ContentValues eventValues, String accountName) {
        // Delete event
        EventHelper.deleteEvent(mContentResolver, eventUri, eventValues);
        // Verify
        verifyEvent(eventValues, ContentUris.parseId(eventUri));
        // Delete as sync adapter
        assertEquals(1,
                EventHelper.deleteEventAsSyncAdapter(mContentResolver, eventUri, accountName));
        // Verify
        Cursor c = EventHelper.getEventByUri(mContentResolver, eventUri);
        assertEquals(0, c.getCount());
        c.close();
    }

    /**
     * Creates an event on the given calendar and verifies it.
     *
     * @param account
     * @param seed
     * @param calendarId
     * @param asSyncAdapter
     * @param values optional pre created set of values; will have several new entries added
     * @return the _id for the new event
     */
    private long createAndVerifyEvent(String account, int seed, long calendarId,
            boolean asSyncAdapter, ContentValues values) {
        // Create an event
        if (values == null) {
            values = EventHelper.getNewEventValues(account, seed, calendarId, asSyncAdapter);
        }
        Uri insertUri = Events.CONTENT_URI;
        if (asSyncAdapter) {
            insertUri = asSyncAdapter(insertUri, account, CTS_TEST_TYPE);
        }
        Uri uri = mContentResolver.insert(insertUri, values);
        assertNotNull(uri);

        // Verify
        EventHelper.addDefaultReadOnlyValues(values, account, asSyncAdapter);
        long eventId = ContentUris.parseId(uri);
        assertTrue(eventId >= 0);

        verifyEvent(values, eventId);
        return eventId;
    }

    /**
     * Updates an event, and verifies that the updates took.
     */
    private void updateAndVerifyEvent(String account, long calendarId, long eventId,
            boolean asSyncAdapter, ContentValues updateValues) {
        Uri uri = Uri.withAppendedPath(Events.CONTENT_URI, String.valueOf(eventId));
        if (asSyncAdapter) {
            uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        }
        int count = mContentResolver.update(uri, updateValues, null, null);

        // Verify
        assertEquals(1, count);
        verifyEvent(updateValues, eventId);
    }

    /**
     * Creates an exception to a recurring event, and verifies it.
     * @param account The account to use.
     * @param originalEventId The ID of the original event.
     * @param values Values for the exception; must include originalInstanceTime.
     * @return The _id for the new event.
     */
    private long createAndVerifyException(String account, long originalEventId,
            ContentValues values, boolean asSyncAdapter) {
        // Create the exception
        Uri uri = Uri.withAppendedPath(Events.CONTENT_EXCEPTION_URI,
                String.valueOf(originalEventId));
        if (asSyncAdapter) {
            uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        }
        Uri resultUri = mContentResolver.insert(uri, values);
        assertNotNull(resultUri);
        long eventId = ContentUris.parseId(resultUri);
        assertTrue(eventId >= 0);
        return eventId;
    }

    /**
     * Deletes an exception to a recurring event.
     * @param account The account to use.
     * @param eventId The ID of the original recurring event.
     * @param excepId The ID of the exception event.
     * @return The number of rows deleted.
     */
    private int deleteException(String account, long eventId, long excepId) {
        Uri uri = Uri.withAppendedPath(Events.CONTENT_EXCEPTION_URI,
                eventId + "/" + excepId);
        uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        return mContentResolver.delete(uri, null, null);
    }

    /**
     * Add some sample attendees to an event.
     */
    private void addAttendees(String account, long eventId, int seed) {
        assertTrue(eventId >= 0);
        AttendeeHelper.addAttendee(mContentResolver, eventId,
                "Attender" + seed,
                CalendarHelper.generateCalendarOwnerEmail(account),
                Attendees.ATTENDEE_STATUS_ACCEPTED,
                Attendees.RELATIONSHIP_ORGANIZER,
                Attendees.TYPE_NONE);
        seed++;

        AttendeeHelper.addAttendee(mContentResolver, eventId,
                "Attender" + seed,
                "attender" + seed + "@example.com",
                Attendees.ATTENDEE_STATUS_TENTATIVE,
                Attendees.RELATIONSHIP_NONE,
                Attendees.TYPE_NONE);
    }

    /**
     * Add some sample reminders to an event.
     */
    private void addReminders(String account, long eventId, int seed) {
        ReminderHelper.addReminder(mContentResolver, eventId, seed * 5, Reminders.METHOD_ALERT);
    }

    /**
     * Creates and removes an event that covers a specific range of dates.  Call this to
     * cause the provider to expand the CalendarMetaData min/max values to include the range.
     * Useful when you want to see the provider expand the instances as the events are added.
     */
    private void expandInstanceRange(String account, long calendarId, String testStart,
            String testEnd, String timeZone) {
        int seed = 0;

        // TODO: this should use an UNTIL rule based on testEnd, not a COUNT
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed,
                calendarId, true, testStart, "PT1H", "FREQ=DAILY;WKST=SU;COUNT=100");

        /*
         * Some of the helper functions modify "eventValues", so we want to make sure we're
         * passing a copy of anything we want to re-use.
         */
        long eventId = createAndVerifyEvent(account, seed, calendarId, true,
                new ContentValues(eventValues));
        assertTrue(eventId >= 0);

        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };
        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "prep-create");
        }
        assertEquals("initial recurrence instance count", 3, instances.getCount());
        instances.close();

        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        removeAndVerifyEvent(eventUri, new ContentValues(eventValues), account);

        instances = getInstances(timeZone, testStart, testEnd, projection,
                new long[] { calendarId });
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "prep-clear");
        }
        assertEquals("initial recurrence instance count", 0, instances.getCount());
        instances.close();

    }

    /**
     * Inserts a new calendar with the given account and seed and verifies it.
     *
     * @param account The account to add the calendar to
     * @param seed A number to use to generate the values
     * @return the created calendar's id
     */
    private long createAndVerifyCalendar(String account, int seed, ContentValues values) {
        // Create a calendar
        if (values == null) {
            values = CalendarHelper.getNewCalendarValues(account, seed);
        }
        Uri syncUri = asSyncAdapter(Calendars.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri uri = mContentResolver.insert(syncUri, values);
        long calendarId = ContentUris.parseId(uri);
        assertTrue(calendarId >= 0);

        verifyCalendar(account, values, calendarId, 1);
        return calendarId;
    }

    /**
     * Deletes a given calendar and verifies no calendars remain on that
     * account.
     *
     * @param account
     * @param id
     */
    private void removeAndVerifyCalendar(String account, long id) {
        // TODO Add code to delete as app and sync adapter and test both

        // Delete
        assertEquals(1, CalendarHelper.deleteCalendarById(mContentResolver, id));

        // Verify
        Cursor c = CalendarHelper.getCalendarsByAccount(mContentResolver, account);
        assertEquals(0, c.getCount());
        c.close();
    }

    /**
     * Check all the fields of a calendar contained in values + id.
     *
     * @param account the account of the calendar
     * @param values the values to check against the db
     * @param id the _id of the calendar
     * @param expectedCount the number of calendars expected on this account
     */
    private void verifyCalendar(String account, ContentValues values, long id, int expectedCount) {
        // Verify
        Cursor c = CalendarHelper.getCalendarsByAccount(mContentResolver, account);
        assertEquals(expectedCount, c.getCount());
        assertTrue(c.moveToFirst());
        while (c.getLong(0) != id) {
            assertTrue(c.moveToNext());
        }
        for (String key : values.keySet()) {
            int index = c.getColumnIndex(key);
            assertTrue("Key " + key + " not in projection", index >= 0);
            assertEquals(key, values.getAsString(key), c.getString(index));
        }
        c.close();
    }

    /**
     * Creates a new _sync_state entry and verifies the contents.
     */
    private long createAndVerifySyncState(String account, ContentValues values) {
        assertNotNull(values);
        Uri syncUri = asSyncAdapter(SyncState.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri uri = mContentResolver.insert(syncUri, values);
        long syncStateId = ContentUris.parseId(uri);
        assertTrue(syncStateId >= 0);

        verifySyncState(account, values, syncStateId);
        return syncStateId;

    }

    /**
     * Removes the _sync_state entry with the specified id, then verifies that it's gone.
     */
    private void removeAndVerifySyncState(String account) {
        assertEquals(1, SyncStateHelper.deleteSyncStateByAccount(mContentResolver, account, true));

        // Verify
        Cursor c = SyncStateHelper.getSyncStateByAccount(mContentResolver, account);
        try {
            assertEquals(0, c.getCount());
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    /**
     * Check all the fields of a _sync_state entry contained in values + id. This assumes
     * a single _sync_state has been created on the given account.
     */
    private void verifySyncState(String account, ContentValues values, long id) {
        // Verify
        Cursor c = SyncStateHelper.getSyncStateByAccount(mContentResolver, account);
        try {
            assertEquals(1, c.getCount());
            assertTrue(c.moveToFirst());
            assertEquals(id, c.getLong(0));
            for (String key : values.keySet()) {
                int index = c.getColumnIndex(key);
                if (key.equals(SyncState.DATA)) {
                    // TODO: can't compare as string, so compare as byte[]
                } else {
                    assertEquals(key, values.getAsString(key), c.getString(index));
                }
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }


    /**
     * Special version of the test runner that does some remote Emma coverage housekeeping.
     */
    // TODO: find if this is still used and if so convert to AndroidJUnitRunner framework
    public static class CalendarEmmaTestRunner extends android.test.InstrumentationTestRunner {
        private static final Uri EMMA_CONTENT_URI =
            Uri.parse("content://" + CalendarContract.AUTHORITY + "/emma");
        private ContentResolver mContentResolver;

        @Override
        public void onStart() {
            mContentResolver = getTargetContext().getContentResolver();

            ContentValues values = new ContentValues();
            values.put("cmd", "start");
            mContentResolver.insert(EMMA_CONTENT_URI, values);

            super.onStart();
        }

        @Override
        public void finish(int resultCode, Bundle results) {
            ContentValues values = new ContentValues();
            values.put("cmd", "stop");
            values.put("outputFileName",
                    Environment.getExternalStorageDirectory() + "/calendar-provider.ec");
            mContentResolver.insert(EMMA_CONTENT_URI, values);
            super.finish(resultCode, results);
        }
    }
}
