19f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/*
29f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Copyright (C) 2008 The Android Open Source Project
39f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
49f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Licensed under the Apache License, Version 2.0 (the "License");
59f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * you may not use this file except in compliance with the License.
69f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * You may obtain a copy of the License at
79f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
89f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *      http://www.apache.org/licenses/LICENSE-2.0
99f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Unless required by applicable law or agreed to in writing, software
119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * distributed under the License is distributed on an "AS IS" BASIS,
129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * See the License for the specific language governing permissions and
149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * limitations under the License.
159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffpackage com.android.providers.calendar;
189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ComponentName;
2081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentProvider;
2145f18d759c5f45a856e1ab709856d5d238d4468fRoboErikimport android.content.ContentResolver;
2281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentUris;
2381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentValues;
2481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.Context;
2581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.Intent;
26ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Makimport android.content.pm.PackageManager;
27ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Makimport android.content.pm.ProviderInfo;
2881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.res.Resources;
299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.Cursor;
30aaa7f0ddf94d402075572b43f39f1866407fbb3fJeff Brownimport android.database.MatrixCursor;
319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteDatabase;
3281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.database.sqlite.SQLiteOpenHelper;
339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.net.Uri;
3408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheungimport android.provider.BaseColumns;
35b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract;
36b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Calendars;
374755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chanimport android.provider.CalendarContract.Colors;
38b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Events;
39b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Instances;
4081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.AndroidTestCase;
4181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.IsolatedContext;
4281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.RenamingDelegatingContext;
439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.test.mock.MockContentResolver;
4481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.mock.MockContext;
4581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.suitebuilder.annotation.SmallTest;
4681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.suitebuilder.annotation.Smoke;
479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.test.suitebuilder.annotation.Suppress;
4845f18d759c5f45a856e1ab709856d5d238d4468fRoboErikimport android.text.TextUtils;
4981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.text.format.DateUtils;
5081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.text.format.Time;
519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.util.Log;
5281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
5381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport java.io.File;
5481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport java.util.Arrays;
55315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.HashMap;
56315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.Map;
57bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chanimport java.util.Set;
58315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.TimeZone;
599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/**
619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Runs various tests on an isolated Calendar provider with its own database.
6225e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio *
6325e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * You can run the tests with the following command line:
6425e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio *
6525e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * adb shell am instrument
6625e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -e debug false
6725e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -w
6825e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -e class com.android.providers.calendar.CalendarProvider2Test
6925e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * com.android.providers.calendar.tests/android.test.InstrumentationTestRunner
7081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang *
7181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * This test no longer extends ProviderTestCase2 because it actually doesn't
7281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * allow you to inject a custom context (which we needed to mock out the calls
7381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * to start a service). We the next best thing, which is copy the relevant code
7481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * from PTC2 and extend AndroidTestCase instead.
759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
7673e55ee06fd7c595495d0ed8971a5dae36fb0399Brett Chabot// flaky test, add back to LargeTest when fixed - bug 2395696
7773e55ee06fd7c595495d0ed8971a5dae36fb0399Brett Chabot// @LargeTest
7881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangpublic class CalendarProvider2Test extends AndroidTestCase {
799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    static final String TAG = "calendar";
809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
810739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private static final String DEFAULT_ACCOUNT_TYPE = "com.google";
820739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private static final String DEFAULT_ACCOUNT = "joe@joe.com";
830739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik
8445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik
8545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    private static final String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
8645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    private static final String[] WHERE_CALENDARS_ARGS = {
8745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        "1"
8845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    };
89f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting    private static final String WHERE_COLOR_ACCOUNT_AND_INDEX = Colors.ACCOUNT_NAME + "=? AND "
90f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            + Colors.ACCOUNT_TYPE + "=? AND " + Colors.COLOR_KEY + "=?";
9145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    private static final String DEFAULT_SORT_ORDER = "begin ASC";
9245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik
9381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    private CalendarProvider2ForTesting mProvider;
949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private SQLiteDatabase mDb;
959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private MetaData mMetaData;
969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Context mContext;
979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private MockContentResolver mResolver;
9819fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana    private Uri mEventsUri = Events.CONTENT_URI;
9974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private Uri mCalendarsUri = Calendars.CONTENT_URI;
1009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int mCalendarId;
1019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected boolean mWipe = false;
103e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    protected boolean mForceDtend = false;
1049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // We need a unique id to put in the _sync_id field so that we can create
1069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // recurrence exceptions that refer to recurring events.
1079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int mGlobalSyncId = 1000;
1089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static final String CALENDAR_URL =
1097e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            "http://www.google.com/calendar/feeds/joe%40joe.com/private/full";
1109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
111ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String TIME_ZONE_AMERICA_ANCHORAGE = "America/Anchorage";
112ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String TIME_ZONE_AMERICA_LOS_ANGELES = "America/Los_Angeles";
113ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String DEFAULT_TIMEZONE = TIME_ZONE_AMERICA_LOS_ANGELES;
114ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
115ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String MOCK_TIME_ZONE_DATABASE_VERSION = "2010a";
116ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
117c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_MINUTE_MILLIS = 60*1000;
118c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_HOUR_MILLIS = 3600*1000;
119c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_WEEK_MILLIS = 7 * 24 * 3600 * 1000;
12081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
12181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    /**
12281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang     * We need a few more stub methods so that our tests can run
12381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang     */
12481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected class MockContext2 extends MockContext {
12581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
12681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
12781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public String getPackageName() {
12881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getPackageName();
12981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
13081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
13181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
13281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public Resources getResources() {
13381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getResources();
13481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
13581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
13681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
13781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public File getDir(String name, int mode) {
13881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            // name the directory so the directory will be seperated from
13981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            // one created through the regular Context
14081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getDir("mockcontext2_" + name, mode);
14181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
14281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
14381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
14481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public ComponentName startService(Intent service) {
14581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return null;
14681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
14781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
14881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
14981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public boolean stopService(Intent service) {
15081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return false;
15181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
152ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak
153ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        @Override
154ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        public PackageManager getPackageManager() {
155ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak            return getContext().getPackageManager();
156ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        }
15781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
15881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
1599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * KeyValue is a simple class that stores a pair of strings representing
1619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * a (key, value) pair.  This is used for updating events.
1629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class KeyValue {
1649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String key;
1659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String value;
1669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public KeyValue(String key, String value) {
1689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.key = key;
1699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.value = value;
1709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
1729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * A generic command interface.  This is used to support a sequence of
1759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * commands that can create events, delete or update events, and then
1769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * check that the state of the database is as expected.
1779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private interface Command {
1799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute();
1809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
1819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to insert a new event into the database.  The event is
1849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * specified by its name (or "title").  All of the event fields (the
1859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * start and end time, whether it is an all-day event, and so on) are
1869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * stored in a separate table (the "mEvents" table).
1879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Insert implements Command {
1899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        EventInfo eventInfo;
1909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Insert(String eventName) {
1929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            eventInfo = findEvent(eventName);
1939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
1969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "insert " + eventInfo.mTitle);
1979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            insertEvent(mCalendarId, eventInfo);
1989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to delete an event, specified by the event name.
2039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Delete implements Command {
2059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String eventName;
2060739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        String account;
2070739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        String accountType;
2089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
2099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2100739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        public Delete(String eventName, int expected, String account, String accountType) {
2119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.eventName = eventName;
2129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
2130739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            this.account = account;
2140739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            this.accountType = accountType;
2159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "delete " + eventName);
2190739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            int rows = deleteMatchingEvents(eventName, account, accountType);
2209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, rows);
2219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to update an event.  The values to update are specified
2269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * with an array of (key, value) pairs.  Both the key and value are
2279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * specified as strings.  Event fields that are not really strings (such
2289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * as DTSTART which is a long) should be converted to the appropriate type
2299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * but that isn't supported yet.  When needed, that can be added here
2309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * by checking for specific keys and converting the associated values.
2319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Update implements Command {
2339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String eventName;
2349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        KeyValue[] pairs;
2359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Update(String eventName, KeyValue[] pairs) {
2379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.eventName = eventName;
2389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.pairs = pairs;
2399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "update " + eventName);
2439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (mWipe) {
2449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Wipe instance table so it will be regenerated
2459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mMetaData.clearInstanceRange();
2469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
2479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            ContentValues map = new ContentValues();
2489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (KeyValue pair : pairs) {
2499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String value = pair.value;
250b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                if (CalendarContract.Events.STATUS.equals(pair.key)) {
2519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    // Do type conversion for STATUS
2529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    map.put(pair.key, Integer.parseInt(value));
2539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                } else {
2549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    map.put(pair.key, value);
2559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
2569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
257ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            if (map.size() == 1 && map.containsKey(Events.STATUS)) {
258ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                updateMatchingEventsStatusOnly(eventName, map);
259ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            } else {
260ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                updateMatchingEvents(eventName, map);
261ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            }
2629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command queries the number of events and compares it to the given
2679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expected value.
2689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class QueryNumEvents implements Command {
2709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
2719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public QueryNumEvents(int expected) {
2739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
2749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = mResolver.query(mEventsUri, null, null, null, null);
2789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, cursor.getCount());
2799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
2809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command dumps the list of events to the log for debugging.
2869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class DumpEvents implements Command {
2889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public DumpEvents() {
2909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = mResolver.query(mEventsUri, null, null, null, null);
2949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dumpCursor(cursor);
2959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
2969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command dumps the list of instances to the log for debugging.
3019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class DumpInstances implements Command {
3039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
3049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
3059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public DumpInstances(String startDate, String endDate) {
3079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
3089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
3099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
3109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
3119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
3129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
3159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dumpCursor(cursor);
3179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
3189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command queries the number of instances and compares it to the given
3239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expected value.
3249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class QueryNumInstances implements Command {
3269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
3279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
3289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
3299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public QueryNumInstances(String startDate, String endDate, int expected) {
3319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
3329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
3339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
3349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
3359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
3369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
3379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
3409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, cursor.getCount());
3429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
3439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * When this command runs it verifies that all of the instances in the
3489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * given range match the expected instances (each instance is specified by
3499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * a start date).
3509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * If you just want to verify that an instance exists in a given date
3519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * range, use {@link VerifyInstance} instead.
3529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class VerifyAllInstances implements Command {
3549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long[] instances;
3559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
3569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
3579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public VerifyAllInstances(String startDate, String endDate, String[] dates) {
3599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
3609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
3619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
3629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
3639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
3649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (dates == null) {
3669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return;
3679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Convert all the instance date strings to UTC milliseconds
3709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int len = dates.length;
3719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.instances = new long[len];
3729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int index = 0;
3739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (String instance : dates) {
3749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.parse3339(instance);
3759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                this.instances[index++] = time.toMillis(false /* use isDst */);
3769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
3809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int len = 0;
3829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instances != null) {
3839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                len = instances.length;
3849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (len != cursor.getCount()) {
3869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                dumpCursor(cursor);
3879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals("number of instances don't match", len, cursor.getCount());
3899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instances == null) {
3919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return;
3929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int beginColumn = cursor.getColumnIndex(Instances.BEGIN);
3959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (cursor.moveToNext()) {
3969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long begin = cursor.getLong(beginColumn);
3979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Search the list of expected instances for a matching start
3999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // time.
4009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean found = false;
4019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                for (long instance : instances) {
4029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    if (instance == begin) {
4039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        found = true;
4049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
4059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    }
4069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!found) {
4089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int titleColumn = cursor.getColumnIndex(Events.TITLE);
4099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int allDayColumn = cursor.getColumnIndex(Events.ALL_DAY);
4109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String title = cursor.getString(titleColumn);
4129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    boolean allDay = cursor.getInt(allDayColumn) != 0;
4139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE |
4149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            DateUtils.FORMAT_24HOUR;
4159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    if (allDay) {
4169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        flags |= DateUtils.FORMAT_UTC;
4179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    } else {
4189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        flags |= DateUtils.FORMAT_SHOW_TIME;
4199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    }
4209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String date = DateUtils.formatDateRange(mContext, begin, begin, flags);
4219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String mesg = String.format("Test failed!"
4229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            + " unexpected instance (\"%s\") at %s",
4239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            title, date);
4249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    Log.e(TAG, mesg);
4259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!found) {
4279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    dumpCursor(cursor);
4289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                assertTrue(found);
4309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
4329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
4349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
4369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * When this command runs it verifies that the given instance exists in
4379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * the given date range.
4389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
4399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class VerifyInstance implements Command {
4409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long instance;
4419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        boolean allDay;
4429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
4439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
4449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        /**
4469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * Creates a command to check that the given range [startDate,endDate]
4479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * contains a specific instance of an event (specified by "date").
4489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         *
4499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param startDate the beginning of the date range
4509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param endDate the end of the date range
4519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param date the date or date-time string of an event instance
4529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         */
4539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public VerifyInstance(String startDate, String endDate, String date) {
4549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
4559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
4569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
4579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
4589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
4599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Convert the instance date string to UTC milliseconds
4619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(date);
4629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            allDay = time.allDay;
4639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            instance = time.toMillis(false /* use isDst */);
4649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
4679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
4689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int beginColumn = cursor.getColumnIndex(Instances.BEGIN);
4699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            boolean found = false;
4709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (cursor.moveToNext()) {
4719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long begin = cursor.getLong(beginColumn);
4729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (instance == begin) {
4749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    found = true;
4759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    break;
4769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (!found) {
4799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE;
4809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (allDay) {
4819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    flags |= DateUtils.FORMAT_UTC;
4829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                } else {
4839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    flags |= DateUtils.FORMAT_SHOW_TIME;
4849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String date = DateUtils.formatDateRange(mContext, instance, instance, flags);
4869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String mesg = String.format("Test failed!"
4879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " cannot find instance at %s",
4889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        date);
4899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, mesg);
4909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertTrue(found);
4929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
4939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
4959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
4979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This class stores all the useful information about an event.
4989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
4999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class EventInfo {
5009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mTitle;
5019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mDescription;
5029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mTimezone;
5039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        boolean mAllDay;
5049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mDtstart;
5059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mDtend;
5069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mRrule;
5079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mDuration;
5089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mOriginalTitle;
5099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mOriginalInstance;
5109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int mSyncId;
511c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        String mCustomAppPackage;
512c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        String mCustomAppUri;
513501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        String mUid2445;
5149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for normal events, using the default timezone
5169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String startDate, String endDate,
5179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay) {
5189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, startDate, endDate, allDay, DEFAULT_TIMEZONE);
5199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for normal events, specifying the timezone
5229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String startDate, String endDate,
5239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay, String timezone) {
5249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, startDate, endDate, allDay, timezone);
5259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String title, String startDate, String endDate,
5289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay, String timezone) {
5299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTitle = title;
5309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time();
5319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = Time.TIMEZONE_UTC;
5339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else if (timezone != null) {
5349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = timezone;
5359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTimezone = time.timezone;
5379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
5389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtstart = time.toMillis(false /* use isDst */);
5399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
5409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtend = time.toMillis(false /* use isDst */);
5419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDuration = null;
5429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mRrule = null;
5439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAllDay = allDay;
544c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            mCustomAppPackage = "CustomAppPackage-" + mTitle;
545c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            mCustomAppUri = "CustomAppUri-" + mTitle;
546501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            mUid2445 = null;
5479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for repeating events, using the default timezone
5509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String description, String startDate, String endDate,
5519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay) {
5529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, rrule, allDay, DEFAULT_TIMEZONE);
5539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for repeating events, specifying the timezone
5569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String description, String startDate, String endDate,
5579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay, String timezone) {
5589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, rrule, allDay, timezone);
5599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String title, String description, String startDate, String endDate,
5629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay, String timezone) {
5639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTitle = title;
5649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDescription = description;
5659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time();
5669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = Time.TIMEZONE_UTC;
5689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else if (timezone != null) {
5699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = timezone;
5709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTimezone = time.timezone;
5729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
5739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtstart = time.toMillis(false /* use isDst */);
5749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (endDate != null) {
5759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.parse3339(endDate);
5769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDtend = time.toMillis(false /* use isDst */);
5779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long days = 1;
5809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (endDate != null) {
5819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    days = (mDtend - mDtstart) / DateUtils.DAY_IN_MILLIS;
5829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
5839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDuration = "P" + days + "D";
5849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else {
5859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long seconds = (mDtend - mDtstart) / DateUtils.SECOND_IN_MILLIS;
5869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDuration = "P" + seconds + "S";
5879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mRrule = rrule;
5899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAllDay = allDay;
5909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for recurrence exceptions, using the default timezone
5939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String originalTitle, String originalInstance, String title,
594c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                String description, String startDate, String endDate, boolean allDay,
595501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                String customPackageName, String customPackageUri, String mUid2445) {
5969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(originalTitle, originalInstance,
597c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                    title, description, startDate, endDate, allDay, DEFAULT_TIMEZONE,
598501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    customPackageName, customPackageUri, mUid2445);
5999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
6009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String originalTitle, String originalInstance,
6029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String title, String description, String startDate, String endDate,
603c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                boolean allDay, String timezone, String customPackageName,
604501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                String customPackageUri, String uid2445) {
6059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mOriginalTitle = originalTitle;
6069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(timezone);
6079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(originalInstance);
6089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mOriginalInstance = time.toMillis(false /* use isDst */);
609c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            mCustomAppPackage = customPackageName;
610c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            mCustomAppUri = customPackageUri;
611501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            mUid2445 = uid2445;
6129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, null /* rrule */, allDay, timezone);
6139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
6149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
6159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class InstanceInfo {
6179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        EventInfo mEvent;
6189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mBegin;
6199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mEnd;
6209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int mExpectedOccurrences;
6219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public InstanceInfo(String eventName, String startDate, String endDate, int expected) {
6239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Find the test index that contains the given event name
6249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mEvent = findEvent(eventName);
6259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(mEvent.mTimezone);
6269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
6279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mBegin = time.toMillis(false /* use isDst */);
6289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
6299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mEnd = time.toMillis(false /* use isDst */);
6309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mExpectedOccurrences = expected;
6319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
6329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
6339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
6359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is the main table of events.  The events in this table are
6369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * referred to by name in other places.
6379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
6389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private EventInfo[] mEvents = {
6399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", false),
6409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal1", "2008-05-26T08:30:00", "2008-05-26T09:30:00", false),
6419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal2", "2008-05-26T14:30:00", "2008-05-26T15:30:00", false),
6429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday0", "2008-05-02T00:00:00", "2008-05-03T00:00:00", true),
6439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday1", "2008-05-02T00:00:00", "2008-05-31T00:00:00", true),
6449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "daily from 5/1/2008 12am to 1am",
6459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T00:00:00", "2008-05-01T01:00:00",
6469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;WKST=SU", false),
6479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily1", "daily from 5/1/2008 8:30am to 9:30am until 5/3/2008 8am",
6489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T08:30:00", "2008-05-01T09:30:00",
6499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T150000Z;WKST=SU", false),
6509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily2", "daily from 5/1/2008 8:45am to 9:15am until 5/3/2008 10am",
6519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T08:45:00", "2008-05-01T09:15:00",
6529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T170000Z;WKST=SU", false),
6539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday daily0", "all-day daily from 5/1/2008",
6549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;WKST=SU", true),
6569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday daily1", "all-day daily from 5/1/2008 until 5/3/2008",
6579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T000000Z;WKST=SU", true),
6599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday weekly0", "all-day weekly from 5/1/2008",
6609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;WKST=SU", true),
6629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday weekly1", "all-day for 2 days weekly from 5/1/2008",
6639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", "2008-05-03",
6649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;WKST=SU", true),
6659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday yearly0", "all-day yearly on 5/1/2008",
6669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T", null,
6679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=YEARLY;WKST=SU", true),
6689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "weekly from 5/6/2008 on Tue 1pm to 2pm",
6699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-06T13:00:00", "2008-05-06T14:00:00",
6709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;BYDAY=TU;WKST=MO", false),
6719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly1", "every 2 weeks from 5/6/2008 on Tue from 2:30pm to 3:30pm",
6729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-06T14:30:00", "2008-05-06T15:30:00",
6739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;INTERVAL=2;BYDAY=TU;WKST=MO", false),
6749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly0", "monthly from 5/20/2008 on the 3rd Tues from 3pm to 4pm",
6759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-20T15:00:00", "2008-05-20T16:00:00",
6769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;BYDAY=3TU;WKST=SU", false),
6779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly1", "monthly from 5/1/2008 on the 1st from 12:00am to 12:10am",
6789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T00:00:00", "2008-05-01T00:10:00",
6799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=1", false),
6809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly2", "monthly from 5/31/2008 on the 31st 11pm to midnight",
6819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-31T23:00:00", "2008-06-01T00:00:00",
6829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=31", false),
6839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-01T00:00:00",
6849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except0", "daily0 exception for 5/1/2008 12am, change to 5/1/2008 2am to 3am",
685501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "2008-05-01T02:00:00", "2008-05-01T01:03:00", false, "AppPkg1", "AppUri1",
686501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "uid2445-1"),
6879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-03T00:00:00",
6889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except1", "daily0 exception for 5/3/2008 12am, change to 5/3/2008 2am to 3am",
689501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "2008-05-03T02:00:00", "2008-05-03T01:03:00", false, "AppPkg2", "AppUri2",
690501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    null),
6919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-02T00:00:00",
6929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except2", "daily0 exception for 5/2/2008 12am, change to 1/2/2008",
693501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "2008-01-02T00:00:00", "2008-01-02T01:00:00", false, "AppPkg3", "AppUri3",
694501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "12345@uid2445"),
6959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "2008-05-13T13:00:00",
6969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except3", "daily0 exception for 5/11/2008 1pm, change to 12/11/2008 1pm",
697501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "2008-12-11T13:00:00", "2008-12-11T14:00:00", false, "AppPkg4", "AppUri4",
698501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    null),
6999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "2008-05-13T13:00:00",
7009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "cancel0", "weekly0 exception for 5/13/2008 1pm",
701501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    "2008-05-13T13:00:00", "2008-05-13T14:00:00", false, "AppPkg5", "AppUri5",
702501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                    null),
7039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("yearly0", "yearly on 5/1/2008 from 1pm to 2pm",
7049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T13:00:00", "2008-05-01T14:00:00",
7059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=YEARLY;WKST=SU", false),
7069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
709bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * This table is used to verify the events generated by mEvents.  It checks that the
7109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * number of instances within a given range matches the expected number
7119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * of instances.
7129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private InstanceInfo[] mInstanceRanges = {
7149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-01T00:01:00", 1),
7159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-01T01:00:00", 1),
7169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 2),
7179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-02T23:59:00", 2),
7189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-02T00:01:00", 1),
7199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-02T01:00:00", 1),
7209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-03T00:00:00", 2),
7219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 31),
7229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-06-01T23:59:00", 32),
7239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily1", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 1),
7259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily1", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 2),
7269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily2", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 1),
7289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily2", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 3),
7299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday daily0", "2008-05-01", "2008-05-07", 7),
7319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday daily1", "2008-05-01", "2008-05-07", 3),
7329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-07", 1),
7339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-08", 2),
7349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-31", 5),
7359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly1", "2008-05-01", "2008-05-31", 5),
7369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday yearly0", "2008-05-01", "2009-04-30", 1),
7379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday yearly0", "2008-05-01", "2009-05-02", 2),
7389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 0),
7409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-06T00:00:00", "2008-05-07T00:00:00", 1),
7419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 4),
7429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 8),
7439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 0),
7459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-06T00:00:00", "2008-05-07T00:00:00", 1),
7469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 2),
7479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 4),
7489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-20T13:00:00", 0),
7509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-20T15:00:00", 1),
7519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-05-31T00:00:00", 0),
7529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-06-17T14:59:00", 0),
7539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-06-17T15:00:00", 1),
7549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 1),
7559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 2),
7569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-05-01T01:00:00", 1),
7589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 1),
7599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:10:00", "2008-05-31T23:59:00", 1),
7609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:11:00", "2008-05-31T23:59:00", 0),
7619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-06-01T00:00:00", 2),
7629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 0),
7649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:10:00", "2008-05-31T23:00:00", 1),
7659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-07-01T00:00:00", 1),
7669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-08-01T00:00:00", 2),
7679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("yearly0", "2008-05-01", "2009-04-30", 1),
7699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("yearly0", "2008-05-01", "2009-05-02", 2),
7709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some events.
7749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mNormalInsertDelete = {
7769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal0"),
7779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal1"),
7789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal2"),
7799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-31T00:01:00", 3),
7800739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
7829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-31T00:01:00", 2),
7830739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal1", 0, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7840739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal2", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
7860739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
7889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some all-day events.
7929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mAlldayInsertDelete = {
7949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("allday0"),
7959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("allday1"),
7969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
7979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-01T00:01:00", 0),
7989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-02T00:00:00", "2008-05-02T00:01:00", 2),
7999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-03T00:00:00", "2008-05-03T00:01:00", 1),
8000739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("allday0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
8019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
8029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-02T00:00:00", "2008-05-02T00:01:00", 1),
8039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-03T00:00:00", "2008-05-03T00:01:00", 1),
8040739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("allday1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
8059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
8069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some repeating events.
8109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mRecurringInsertDelete = {
8129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
8139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily1"),
8149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
8159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-02T00:01:00", 3),
8169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T01:01:00", "2008-05-02T00:01:00", 2),
8179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00", 6),
8180739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("daily1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
8199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
8209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-02T00:01:00", 2),
8219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00", 4),
8220739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("daily0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
8239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
8249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
8289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception that moves an event outside the expansion window.  It checks that the
8299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * recurrence exception does not occur in the Instances database table.
8309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Bug 1642665
8319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithMovedRecurrence = {
8339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
8349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
8359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-03T00:00:00", }),
8379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except2"),
8389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
8399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-03T00:00:00"}),
8409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands deletes (cancels) one instance of a recurrence.
8449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mCancelInstance = {
8469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("weekly0"),
8479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-22T00:01:00",
8489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-06T13:00:00", "2008-05-13T13:00:00",
8499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-20T13:00:00", }),
8509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("cancel0"),
8519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("cancel0", new KeyValue[] {
852b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    new KeyValue(CalendarContract.Events.STATUS,
853b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        Integer.toString(CalendarContract.Events.STATUS_CANCELED)),
8549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
8559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-22T00:01:00",
8569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-06T13:00:00",
8579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-20T13:00:00", }),
8589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
8619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception that moves an event from outside the expansion window into the
8629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expansion window.
8639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithMovedRecurrence2 = {
8659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("weekly0"),
8669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-12-01T00:00:00", "2008-12-22T00:01:00",
8679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-12-02T13:00:00", "2008-12-09T13:00:00",
8689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-12-16T13:00:00", }),
8699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except3"),
8709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-12-01T00:00:00", "2008-12-22T00:01:00",
8719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-12-02T13:00:00", "2008-12-09T13:00:00",
8729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-12-11T13:00:00", "2008-12-16T13:00:00", }),
8739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
8769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception and then changes the end time of the recurring event.  It then
8779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * checks that the recurrence exception does not occur in the Instances
8789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * database table.
8799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[]
8819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mExceptionWithTruncatedRecurrence = {
8829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
8839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify 4 occurrences of the "daily0" repeating event
8849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8867e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T00:00:00", "2008-05-04T00:00:00"}),
8879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except1"),
8889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
8899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that one of the 4 occurrences has its start time changed
8919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // so that it now matches the recurrence exception.
8929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8947e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T02:00:00", "2008-05-04T00:00:00"}),
8959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Change the end time of "daily0" but it still includes the
8979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // recurrence exception.
8989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("daily0", new KeyValue[] {
8999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new KeyValue(Events.RRULE, "FREQ=DAILY;UNTIL=20080505T150000Z;WKST=SU"),
9009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
9019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that the recurrence exception is still there
9039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
9049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
9057e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T02:00:00", "2008-05-04T00:00:00"}),
9069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This time change the end time of "daily0" so that it excludes
9079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // the recurrence exception.
9089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("daily0", new KeyValue[] {
9099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new KeyValue(Events.RRULE, "FREQ=DAILY;UNTIL=20080502T150000Z;WKST=SU"),
9109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
9119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // The server will cancel the out-of-range exception.
9129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // It would be nice for the provider to handle this automatically,
9139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // but for now simulate the server-side cancel.
9149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("except1", new KeyValue[] {
915b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                new KeyValue(CalendarContract.Events.STATUS,
916b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        Integer.toString(CalendarContract.Events.STATUS_CANCELED)),
9179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
9189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that the recurrence exception does not appear.
9199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
9209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00"}),
9219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
9229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
9249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Bug 135848.  Ensure that a recurrence exception is displayed even if the recurrence
9259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * is not present.
9269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
9279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithNoRecurrence = {
9287e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            new Insert("except0"),
9299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
9309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
9319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T02:00:00"}),
9329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
9339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private EventInfo findEvent(String name) {
9359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
9369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
9379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
9389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (name.equals(event.mTitle)) {
9399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return event;
9409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
9419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
9429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return null;
9439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
9449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
9469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected void setUp() throws Exception {
9479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        super.setUp();
94881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // This code here is the code that was originally in ProviderTestCase2
94981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mResolver = new MockContentResolver();
95081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
95181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String filenamePrefix = "test.";
95281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
95381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                new MockContext2(), // The context that most methods are delegated to
95481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                getContext(), // The context that file methods are delegated to
95581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                filenamePrefix);
956ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        mContext = new IsolatedContext(mResolver, targetContextWrapper) {
957ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak            @Override
958ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak            public Object getSystemService(String name) {
959ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                // for accessing wakelock.
960ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                if (Context.POWER_SERVICE.equals(name)) {
961ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                    return getContext().getSystemService(name);
962ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                }
963ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                return super.getSystemService(name);
964ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak            }
965ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        };
9669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
96781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mProvider = new CalendarProvider2ForTesting();
968ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        ProviderInfo info = new ProviderInfo();
969ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        info.authority = CalendarContract.AUTHORITY;
970ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        mProvider.attachInfoForTesting(mContext, info);
97181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
972b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.addProvider(CalendarContract.AUTHORITY, mProvider);
9739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mResolver.addProvider("subscribedfeeds", new MockProvider("subscribedfeeds"));
9749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mResolver.addProvider("sync", new MockProvider("sync"));
9759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mMetaData = getProvider().mMetaData;
977e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        mForceDtend = false;
978c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
979c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
980c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        mDb = helper.getWritableDatabase();
981c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        wipeAndInitData(helper, mDb);
9829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
9839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
98481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @Override
98581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected void tearDown() throws Exception {
98681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
98781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            mDb.close();
98881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            mDb = null;
98981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            getProvider().getDatabaseHelper().close();
99081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } catch (IllegalStateException e) {
99181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            e.printStackTrace();
99281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
99381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        super.tearDown();
99481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
99526d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff
996c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    public void wipeAndInitData(SQLiteOpenHelper helper, SQLiteDatabase db)
997c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            throws CalendarCache.CacheException {
998c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.beginTransaction();
999c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1000c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Clean tables
1001c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Calendars", null, null);
1002c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Events", null, null);
1003c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("EventsRawTimes", null, null);
1004c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Instances", null, null);
1005c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarMetaData", null, null);
1006c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarCache", null, null);
1007c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Attendees", null, null);
1008c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Reminders", null, null);
1009c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarAlerts", null, null);
1010c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("ExtendedProperties", null, null);
1011c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1012c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Set CalendarCache data
1013c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        initCalendarCacheLocked(helper, db);
1014c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1015c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // set CalendarMetaData data
1016c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long now = System.currentTimeMillis();
1017c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        ContentValues values = new ContentValues();
1018c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("localTimezone", "America/Los_Angeles");
1019c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("minInstance", 1207008000000L); // 1st April 2008
1020c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("maxInstance", now + ONE_WEEK_MILLIS);
1021c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.insert("CalendarMetaData", null, values);
1022c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1023c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.setTransactionSuccessful();
1024c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.endTransaction();
1025c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    }
1026c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1027c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private void initCalendarCacheLocked(SQLiteOpenHelper helper, SQLiteDatabase db)
1028c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            throws CalendarCache.CacheException {
1029c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
1030c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1031c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String localTimezone = TimeZone.getDefault().getID();
1032c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
1033c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Set initial values
1034c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_DATABASE_VERSION, "2010k");
1035c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_TYPE, CalendarCache.TIMEZONE_TYPE_AUTO);
1036c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_INSTANCES, localTimezone);
1037c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS, localTimezone);
103826d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff    }
103926d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff
104081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected CalendarProvider2ForTesting getProvider() {
104181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        return mProvider;
10429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
10439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
10459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Dumps the contents of the given cursor to the log.  For debugging.
10469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param cursor the database cursor
10479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
10489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void dumpCursor(Cursor cursor) {
10499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToPosition(-1);
10509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String[] cols = cursor.getColumnNames();
10519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "dumpCursor() count: " + cursor.getCount());
10539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int index = 0;
10549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
10559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, index + " {");
10569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (int i = 0; i < cols.length; i++) {
10579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.i(TAG, "    " + cols[i] + '=' + cursor.getString(i));
10589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
10599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "}");
10609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            index += 1;
10619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToPosition(-1);
10639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
10649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int insertCal(String name, String timezone) {
10660739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        return insertCal(name, timezone, DEFAULT_ACCOUNT);
1067205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    }
1068205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
1069bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
1070bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Creates a new calendar, with the provided name, time zone, and account name.
1071bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     *
1072bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * @return the new calendar's _ID value
1073bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
1074205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    private int insertCal(String name, String timezone, String account) {
10759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues m = new ContentValues();
10769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Calendars.NAME, name);
107702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        m.put(Calendars.CALENDAR_DISPLAY_NAME, name);
107824abf95cb69e8040af1a8dc2faace1bfb3ab505cAndy McFadden        m.put(Calendars.CALENDAR_COLOR, 0xff123456);
107902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        m.put(Calendars.CALENDAR_TIME_ZONE, timezone);
10804067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        m.put(Calendars.VISIBLE, 1);
1081fa332ecedc0c340109811552407142f6e4f600b2RoboErik        m.put(Calendars.CAL_SYNC1, CALENDAR_URL);
1082c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        m.put(Calendars.OWNER_ACCOUNT, account);
1083c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        m.put(Calendars.ACCOUNT_NAME,  account);
1084c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        m.put(Calendars.ACCOUNT_TYPE, DEFAULT_ACCOUNT_TYPE);
1085eb7ee6232dc1f62b7bf71abc8e706cbf81b00235Fabrice Di Meglio        m.put(Calendars.SYNC_EVENTS,  1);
10869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10870739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        Uri url = mResolver.insert(
10880739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                addSyncQueryParams(mCalendarsUri, account, DEFAULT_ACCOUNT_TYPE), m);
10899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String id = url.getLastPathSegment();
10909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return Integer.parseInt(id);
10919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
10929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10934755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan    private String obsToString(Object... objs) {
10944755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        StringBuilder bob = new StringBuilder();
10954755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
10964755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        for (Object obj : objs) {
10974755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan            bob.append(obj.toString());
10984755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan            bob.append('#');
10994755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        }
11004755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
11014755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        return bob.toString();
11024755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan    }
11034755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
110410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    private Uri insertColor(long colorType, String colorKey, long color) {
11054755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        ContentValues m = new ContentValues();
11064755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.ACCOUNT_NAME, DEFAULT_ACCOUNT);
11074755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.ACCOUNT_TYPE, DEFAULT_ACCOUNT_TYPE);
11084755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.DATA, obsToString(colorType, colorKey, color));
11094755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.COLOR_TYPE, colorType);
11104755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.COLOR_KEY, colorKey);
11114755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        m.put(Colors.COLOR, color);
11124755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
11134755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        Uri uri = CalendarContract.Colors.CONTENT_URI;
11144755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
111510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        return mResolver.insert(addSyncQueryParams(uri, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), m);
111610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    }
111710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
111810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    private void updateAndCheckColor(long colorId, long colorType, String colorKey, long color) {
111910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
112010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        Uri uri = CalendarContract.Colors.CONTENT_URI;
112110651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
112210651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        final String where = Colors.ACCOUNT_NAME + "=? AND " + Colors.ACCOUNT_TYPE + "=? AND "
112310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan                + Colors.COLOR_TYPE + "=? AND " + Colors.COLOR_KEY + "=?";
112410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
112510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        String[] selectionArgs = new String[] {
112610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan                DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE, Long.toString(colorType), colorKey
112710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        };
112810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
112910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        ContentValues cv = new ContentValues();
113010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        cv.put(Colors.COLOR, color);
113110651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        cv.put(Colors.DATA, obsToString(colorType, colorKey, color));
113210651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
113310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        int count = mResolver.update(
113410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan                addSyncQueryParams(uri, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), cv, where,
113510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan                selectionArgs);
113610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
113710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        checkColor(colorId, colorType, colorKey, color);
113810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
113910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        assertEquals(1, count);
11404755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan    }
11414755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
1142bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
1143bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Constructs a URI from a base URI (e.g. "content://com.android.calendar/calendars"),
1144bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * an account name, and an account type.
1145bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
11460739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private Uri addSyncQueryParams(Uri uri, String account, String accountType) {
1147b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        return uri.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
1148c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
1149c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
11500739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    }
11510739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik
115274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private int deleteMatchingCalendars(String selection, String[] selectionArgs) {
115374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        return mResolver.delete(mCalendarsUri, selection, selectionArgs);
115474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
115574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
11569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Uri insertEvent(int calId, EventInfo event) {
1157c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        return insertEvent(calId, event, null);
1158c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    }
1159c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1160c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private Uri insertEvent(int calId, EventInfo event, ContentValues cv) {
11619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (mWipe) {
11629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Wipe instance table so it will be regenerated
11639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mMetaData.clearInstanceRange();
11649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1165c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1166c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        if (cv == null) {
1167c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cv = eventInfoToContentValues(calId, event);
1168c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        }
1169c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1170c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        Uri url = mResolver.insert(mEventsUri, cv);
1171c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1172c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        // Create a fake _sync_id and add it to the event.  Update the database
1173c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        // directly so that we don't trigger any validation checks in the
1174c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        // CalendarProvider.
1175c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        long id = ContentUris.parseId(url);
1176c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        mDb.execSQL("UPDATE Events SET _sync_id=" + mGlobalSyncId + " WHERE _id=" + id);
1177c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        event.mSyncId = mGlobalSyncId;
1178c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        mGlobalSyncId += 1;
1179c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1180c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        return url;
1181c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    }
1182c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1183c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private ContentValues eventInfoToContentValues(int calId, EventInfo event) {
11849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues m = new ContentValues();
11859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.CALENDAR_ID, calId);
11869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.TITLE, event.mTitle);
11879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.DTSTART, event.mDtstart);
11889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.ALL_DAY, event.mAllDay ? 1 : 0);
11899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1190e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        if (event.mRrule == null || mForceDtend) {
11919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a normal event
11929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DTEND, event.mDtend);
119358993e879a53f5454b36036da9799550f2ae0814Andy McFadden            m.remove(Events.DURATION);
1194e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        }
1195e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        if (event.mRrule != null) {
11969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a repeating event
11979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.RRULE, event.mRrule);
11989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DURATION, event.mDuration);
119958993e879a53f5454b36036da9799550f2ae0814Andy McFadden            m.remove(Events.DTEND);
12009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
12019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mDescription != null) {
12039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DESCRIPTION, event.mDescription);
12049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
12059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mTimezone != null) {
12069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.EVENT_TIMEZONE, event.mTimezone);
12079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1208c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        if (event.mCustomAppPackage != null) {
1209c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            m.put(Events.CUSTOM_APP_PACKAGE, event.mCustomAppPackage);
1210c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        }
1211c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        if (event.mCustomAppUri != null) {
1212c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            m.put(Events.CUSTOM_APP_URI, event.mCustomAppUri);
1213c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        }
1214501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        if (event.mUid2445 != null) {
1215501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            m.put(Events.UID_2445, event.mUid2445);
1216501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        }
12179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mOriginalTitle != null) {
12199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a recurrence exception.
12209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo recur = findEvent(event.mOriginalTitle);
12219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertNotNull(recur);
12229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            String syncId = String.format("%d", recur.mSyncId);
1223c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            m.put(Events.ORIGINAL_SYNC_ID, syncId);
12249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.ORIGINAL_ALL_DAY, recur.mAllDay ? 1 : 0);
12259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.ORIGINAL_INSTANCE_TIME, event.mOriginalInstance);
12269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1227c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        return m;
12289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
12299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
12319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Deletes all the events that match the given title.
12329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param title the given title to match events on
12339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @return the number of rows deleted
12349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
12350739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private int deleteMatchingEvents(String title, String account, String accountType) {
12369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor = mResolver.query(mEventsUri, new String[] { Events._ID },
12379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "title=?", new String[] { title }, null);
12389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numRows = 0;
12399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
12409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            long id = cursor.getLong(0);
1241205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // Do delete as a sync adapter so event is really deleted, not just marked
1242205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // as deleted.
12430739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            Uri uri = updatedUri(ContentUris.withAppendedId(Events.CONTENT_URI, id), true, account,
12440739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                    accountType);
12459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numRows += mResolver.delete(uri, null, null);
12469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
12479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return numRows;
12499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
12509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
12529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Updates all the events that match the given title.
12539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param title the given title to match events on
12549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @return the number of rows updated
12559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
12569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int updateMatchingEvents(String title, ContentValues values) {
12579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String[] projection = new String[] {
12589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events._ID,
12599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DTSTART,
12609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DTEND,
12619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DURATION,
12629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.ALL_DAY,
12639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.RRULE,
12649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.EVENT_TIMEZONE,
1265c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                Events.ORIGINAL_SYNC_ID,
12669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        };
12679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor = mResolver.query(mEventsUri, projection,
12689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "title=?", new String[] { title }, null);
12699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numRows = 0;
12709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
12719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            long id = cursor.getLong(0);
12729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // If any of the following fields are being changed, then we need
12749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // to include all of them.
12759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (values.containsKey(Events.DTSTART) || values.containsKey(Events.DTEND)
12769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.DURATION) || values.containsKey(Events.ALL_DAY)
12779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.RRULE)
12789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.EVENT_TIMEZONE)
1279b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    || values.containsKey(CalendarContract.Events.STATUS)) {
12809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long dtstart = cursor.getLong(1);
12819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long dtend = cursor.getLong(2);
12829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String duration = cursor.getString(3);
12839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay = cursor.getInt(4) != 0;
12849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule = cursor.getString(5);
12859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String timezone = cursor.getString(6);
12869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String originalEvent = cursor.getString(7);
12879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DTSTART)) {
12899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DTSTART, dtstart);
12909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
12919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Don't add DTEND for repeating events
12929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DTEND) && rrule == null) {
12939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DTEND, dtend);
12949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
12959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DURATION) && duration != null) {
12969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DURATION, duration);
12979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
12989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.ALL_DAY)) {
12999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.ALL_DAY, allDay ? 1 : 0);
13009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
13019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.RRULE) && rrule != null) {
13029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.RRULE, rrule);
13039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
13049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.EVENT_TIMEZONE) && timezone != null) {
13059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.EVENT_TIMEZONE, timezone);
13069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
1307c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                if (!values.containsKey(Events.ORIGINAL_SYNC_ID) && originalEvent != null) {
1308c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                    values.put(Events.ORIGINAL_SYNC_ID, originalEvent);
13099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
13109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
13119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
13139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numRows += mResolver.update(uri, values, null, null);
13149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
13159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
13169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return numRows;
13179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
13189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1319ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    /**
1320ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * Updates the status of all the events that match the given title.
1321ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * @param title the given title to match events on
1322ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * @return the number of rows updated
1323ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     */
1324ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    private int updateMatchingEventsStatusOnly(String title, ContentValues values) {
1325ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        String[] projection = new String[] {
1326ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                Events._ID,
1327ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        };
1328ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        if (values.size() != 1 && !values.containsKey(Events.STATUS)) {
1329ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            return 0;
1330ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        }
1331ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        Cursor cursor = mResolver.query(mEventsUri, projection,
1332ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                "title=?", new String[] { title }, null);
1333ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        int numRows = 0;
1334ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        while (cursor.moveToNext()) {
1335ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            long id = cursor.getLong(0);
1336ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
1337ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
1338ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            numRows += mResolver.update(uri, values, null, null);
1339ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        }
1340ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        cursor.close();
1341ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        return numRows;
1342ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    }
1343ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
1344ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
13459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void deleteAllEvents() {
13469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mDb.execSQL("DELETE FROM Events;");
13479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mMetaData.clearInstanceRange();
13489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
13499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1350f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting    /**
1351f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting     * Creates an updated URI that includes query parameters that identify the source as a
1352f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting     * sync adapter.
1353f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting     */
1354f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting    static Uri asSyncAdapter(Uri uri, String account, String accountType) {
1355f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        return uri.buildUpon()
1356f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,
1357f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                        "true")
1358f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
1359f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
1360f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting    }
1361ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak
1362f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting    public void testInsertUpdateDeleteColor() throws Exception {
136310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        // Calendar Color
136410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        long colorType = Colors.TYPE_CALENDAR;
136510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        String colorKey = "123";
136610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        long colorValue = 11;
136710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        long colorId = insertAndCheckColor(colorType, colorKey, colorValue);
136810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
13694755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        try {
137010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan            insertAndCheckColor(colorType, colorKey, colorValue);
13714755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan            fail("Expected to fail with duplicate insertion");
13724755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        } catch (IllegalArgumentException iae) {
13734755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan            // good
13744755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        }
13754755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
137610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        // Test Update
137710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        colorValue += 11;
137810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        updateAndCheckColor(colorId, colorType, colorKey, colorValue);
137910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
138010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        // Event Color
138110651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        colorType = Colors.TYPE_EVENT;
138210651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        colorValue += 11;
138310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        colorId = insertAndCheckColor(colorType, colorKey, colorValue);
138410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        try {
138510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan            insertAndCheckColor(colorType, colorKey, colorValue);
138610651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan            fail("Expected to fail with duplicate insertion");
138710651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        } catch (IllegalArgumentException iae) {
138810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan            // good
138910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        }
139010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
1391f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        // Create an event with the old color value.
1392f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        int calendarId0 = insertCal("Calendar0", DEFAULT_TIMEZONE);
1393f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        String title = "colorTest";
1394f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        ContentValues cv = this.eventInfoToContentValues(calendarId0, mEvents[0]);
1395f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        cv.put(Events.EVENT_COLOR_KEY, colorKey);
1396f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        cv.put(Events.TITLE, title);
1397f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        Uri uri = insertEvent(calendarId0, mEvents[0], cv);
1398f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        Cursor c = mResolver.query(uri, new String[] {Events.EVENT_COLOR},  null, null, null);
1399f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        try {
1400f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            // Confirm the color is set.
1401f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            c.moveToFirst();
1402f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            assertEquals(colorValue, c.getInt(0));
1403f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        } finally {
1404f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            if (c != null) {
1405f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                c.close();
1406f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            }
1407f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        }
1408f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting
140910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        // Test Update
141010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        colorValue += 11;
141110651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        updateAndCheckColor(colorId, colorType, colorKey, colorValue);
1412f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting
1413f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        // Check if color was updated in event.
1414f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        c = mResolver.query(uri, new String[] {Events.EVENT_COLOR}, null, null, null);
1415f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        try {
1416f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            c.moveToFirst();
1417f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            assertEquals(colorValue, c.getInt(0));
1418f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        } finally {
1419f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            if (c != null) {
1420f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                c.close();
1421f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            }
1422f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        }
1423f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting
1424f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        // Test Delete
1425f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        Uri colSyncUri = asSyncAdapter(Colors.CONTENT_URI, DEFAULT_ACCOUNT,
1426f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                DEFAULT_ACCOUNT_TYPE);
1427f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        try {
1428f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            // Delete should fail if color referenced by an event.
1429f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            mResolver.delete(colSyncUri, WHERE_COLOR_ACCOUNT_AND_INDEX,
1430f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                    new String[] {DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE, colorKey});
1431f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            fail("Should not allow deleting referenced color");
1432f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        } catch (UnsupportedOperationException e) {
1433f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting            // Exception expected.
1434f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        }
1435f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        Cursor cursor = mResolver.query(Colors.CONTENT_URI, new String[] {Colors.COLOR_KEY},
1436f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                Colors.COLOR_KEY + "=? AND " + Colors.COLOR_TYPE + "=?",
1437f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                new String[] {colorKey, Long.toString(colorType)}, null);
1438f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        assertEquals(1, cursor.getCount());
1439f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting
1440f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        // Try again, by deleting the event, then the color.
1441f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        assertEquals(1, deleteMatchingEvents(title, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE));
1442f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        mResolver.delete(colSyncUri, WHERE_COLOR_ACCOUNT_AND_INDEX,
1443f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                new String[] {DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE, colorKey});
1444f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        cursor = mResolver.query(Colors.CONTENT_URI, new String[] {Colors.COLOR_KEY},
1445f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                Colors.COLOR_KEY + "=? AND " + Colors.COLOR_TYPE + "=?",
1446f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting                new String[] {colorKey, Long.toString(colorType)}, null);
1447f4b1756f88c34efefb33b4103230ee334d9c9262Sara Ting        assertEquals(0, cursor.getCount());
14484755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan    }
14494755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
145010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    private void checkColor(long colorId, long colorType, String colorKey, long color) {
14514755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        String[] projection = new String[] {
14524755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.ACCOUNT_NAME, // 0
14534755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.ACCOUNT_TYPE, // 1
14544755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.COLOR_TYPE,   // 2
14554755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.COLOR_KEY,    // 3
14564755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.COLOR,        // 4
14574755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors._ID,          // 5
14584755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                Colors.DATA,         // 6
14594755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        };
14604755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        Cursor cursor = mResolver.query(Colors.CONTENT_URI, projection, Colors.COLOR_KEY
14614755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                + "=? AND " + Colors.COLOR_TYPE + "=?", new String[] {
14624755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan                colorKey, Long.toString(colorType)
14634755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        }, null /* sortOrder */);
14644755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
14654755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(1, cursor.getCount());
14664755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
14674755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertTrue(cursor.moveToFirst());
14684755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(DEFAULT_ACCOUNT, cursor.getString(0));
14694755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(DEFAULT_ACCOUNT_TYPE, cursor.getString(1));
14704755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(colorType, cursor.getLong(2));
14714755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(colorKey, cursor.getString(3));
14724755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(color, cursor.getLong(4));
147310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        assertEquals(colorId, cursor.getLong(5));
14744755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        assertEquals(obsToString(colorType, colorKey, color), cursor.getString(6));
14754755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan        cursor.close();
14764755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan    }
14774755452ab84f704f8ce4d7e0bf61a9faeeee2b99Michael Chan
147810651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    private long insertAndCheckColor(long colorType, String colorKey, long color) {
147910651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        Uri uri = insertColor(colorType, colorKey, color);
148010651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        long id = Long.parseLong(uri.getLastPathSegment());
148110651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
148210651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        checkColor(id, colorType, colorKey, color);
148310651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan        return id;
148410651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan    }
148510651e7b4f209a03649b9eac62facbc7bf864d17Michael Chan
14869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInsertNormalEvents() throws Exception {
1487c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        final int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
1488c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        Cursor cursor = mResolver.query(mEventsUri, null, null, null, null);
14899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
14909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
14919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
14929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Keep track of the number of normal events
1493c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        int numOfInserts = 0;
14949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
14959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // "begin" is the earliest start time of all the normal events,
14969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // and "end" is the latest end time of all the normal events.
14979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin = 0, end = 0;
14989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
14999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
1500c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        Uri[] uris = new Uri[len];
1501c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        ContentValues[] cvs = new ContentValues[len];
15029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
15039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
15049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Skip repeating events and recurrence exceptions
15059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (event.mRrule != null || event.mOriginalTitle != null) {
15069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                continue;
15079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
1508c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (numOfInserts == 0) {
15099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                begin = event.mDtstart;
15109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                end = event.mDtend;
15119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else {
15129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (begin > event.mDtstart) {
15139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    begin = event.mDtstart;
15149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
15159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (end < event.mDtend) {
15169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    end = event.mDtend;
15179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
15189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
1519c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1520c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cvs[ii] = eventInfoToContentValues(calId, event);
1521c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            uris[ii] = insertEvent(calId, event, cvs[ii]);
1522c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            numOfInserts += 1;
15239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
15249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1525c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        // Verify
1526c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        for (int i = 0; i < len; i++) {
1527c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (cvs[i] == null) continue;
1528c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            assertNotNull(uris[i]);
1529c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cursor = mResolver.query(uris[i], null, null, null, null);
1530c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            assertEquals("Item " + i + " not found", 1, cursor.getCount());
1531c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            verifyContentValueAgainstCursor(cvs[i], cvs[i].keySet(), cursor);
1532c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cursor.close();
1533c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        }
15349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query all
15369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
1537c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        assertEquals(numOfInserts, cursor.getCount());
15389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
15399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Check that the Instances table has one instance of each of the
15419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // normal events.
15429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = queryInstances(begin, end);
1543c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        assertEquals(numOfInserts, cursor.getCount());
15449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
15459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
15469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInsertRepeatingEvents() throws Exception {
15489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
15499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
15509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int calId = insertCal("Calendar0", "America/Los_Angeles");
15529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
15549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
15559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
15569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Keep track of the number of repeating events
1558c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        int numOfInserts = 0;
15599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
1561c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        Uri[] uris = new Uri[len];
1562c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        ContentValues[] cvs = new ContentValues[len];
15639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
15649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
15659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Skip normal events
15669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (event.mRrule == null) {
15679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                continue;
15689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
1569c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cvs[ii] = eventInfoToContentValues(calId, event);
1570c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            uris[ii] = insertEvent(calId, event, cvs[ii]);
1571c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            numOfInserts += 1;
15729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
15739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1574c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        // Verify
1575c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        for (int i = 0; i < len; i++) {
1576c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (cvs[i] == null) continue;
1577c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            assertNotNull(uris[i]);
1578c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cursor = mResolver.query(uris[i], null, null, null, null);
1579c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            assertEquals("Item " + i + " not found", 1, cursor.getCount());
1580c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            verifyContentValueAgainstCursor(cvs[i], cvs[i].keySet(), cursor);
1581c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            cursor.close();
1582c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        }
15839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
15849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query all
15859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
1586c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        assertEquals(numOfInserts, cursor.getCount());
15879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
15889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
15899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1590e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    // Force a dtend value to be set and make sure instance expansion still works
1591e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    public void testInstanceRangeDtend() throws Exception {
1592e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        mForceDtend = true;
1593e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        testInstanceRange();
1594e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    }
1595e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff
15969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInstanceRange() throws Exception {
15979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
15989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
15999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int calId = insertCal("Calendar0", "America/Los_Angeles");
16019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
16039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
16049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
16059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mInstanceRanges.length;
16079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
16089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            InstanceInfo instance = mInstanceRanges[ii];
16099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = instance.mEvent;
16109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            url = insertEvent(calId, event);
16119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor = queryInstances(instance.mBegin, instance.mEnd);
16129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instance.mExpectedOccurrences != cursor.getCount()) {
16139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, "Test failed! Instance index: " + ii);
16149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, "title: " + event.mTitle + " desc: " + event.mDescription
16159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " [begin,end]: [" + instance.mBegin + " " + instance.mEnd + "]"
16169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " expected: " + instance.mExpectedOccurrences);
16179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                dumpCursor(cursor);
16189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
16199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(instance.mExpectedOccurrences, cursor.getCount());
16209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
1621205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // Delete as sync_adapter so event is really deleted.
16220739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            int rows = mResolver.delete(
16230739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                    updatedUri(url, true, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
1624205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff                    null /* selection */, null /* selection args */);
16259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(1, rows);
16269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
16279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
16289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
162981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public static <T> void assertArrayEquals(T[] expected, T[] actual) {
163081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        if (!Arrays.equals(expected, actual)) {
163181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            fail("expected:<" + Arrays.toString(expected) +
163281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                "> but was:<" + Arrays.toString(actual) + ">");
163381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
163481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
163581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
163681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
1637dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    public void testEscapeSearchToken() {
1638dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String token = "test";
1639dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String expected = "test";
1640dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1641dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1642dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "%";
1643dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#%";
1644dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1645dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1646dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "_";
1647dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#_";
1648dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1649dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1650dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "#";
1651dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "##";
1652dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1653dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1654dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "##";
1655dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "####";
1656dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1657dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1658dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "%_#";
1659dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#%#_##";
1660dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1661dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1662dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "blah%blah";
1663dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "blah#%blah";
1664dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1665dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    }
1666dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1667dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    @SmallTest @Smoke
166881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testTokenizeSearchQuery() {
166981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String query = "";
1670dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String[] expectedTokens = new String[] {};
167181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
167281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
167381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "a";
167481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"a"};
167581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
167681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
1677dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "word";
1678dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"word"};
1679dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1680dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
168181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "two words";
168281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"two", "words"};
168381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
168481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
168581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "test, punctuation.";
168681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"test", "punctuation"};
168781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1688dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1689dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "\"test phrase\"";
1690dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"test phrase"};
1691dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1692dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1693dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "unquoted \"this is quoted\"";
1694dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"unquoted", "this is quoted"};
1695dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1696dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1697dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = " \"this is quoted\"  unquoted ";
1698dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"this is quoted", "unquoted"};
1699dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1700dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1701dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "escap%e m_e";
1702dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"escap#%e", "m#_e"};
1703dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1704dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1705dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "'a bunch' of malformed\" things";
1706dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"a", "bunch", "of", "malformed", "things"};
1707dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1708dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1709dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "''''''....,.''trim punctuation";
1710dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"trim", "punctuation"};
1711dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
171281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
171381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
171481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
171581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testConstructSearchWhere() {
171681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String[] tokens = new String[] {"red"};
1717dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String expected = "(title LIKE ? ESCAPE \"#\" OR "
171818f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
171918f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
172018f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
172118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
172281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
172381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
172481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {};
172581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expected = "";
172681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
172781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
172881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red", "green"};
1729dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "(title LIKE ? ESCAPE \"#\" OR "
1730dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "description LIKE ? ESCAPE \"#\" OR "
173118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "eventLocation LIKE ? ESCAPE \"#\" OR "
173218f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
173318f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" ) AND "
1734dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "(title LIKE ? ESCAPE \"#\" OR "
1735dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "description LIKE ? ESCAPE \"#\" OR "
173618f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "eventLocation LIKE ? ESCAPE \"#\" OR "
173718f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
173818f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
173981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
174081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
174181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red blue", "green"};
1742dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "(title LIKE ? ESCAPE \"#\" OR "
174318f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
174418f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
174518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
174618f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" ) AND "
174718f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "(title LIKE ? ESCAPE \"#\" OR "
174818f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
174918f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
175018f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
175118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
175281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
175381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
175481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
175581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
175681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testConstructSearchArgs() {
175781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String[] tokens = new String[] {"red"};
1758ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        String[] expected = new String[] {"%red%", "%red%",
175918f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%red%", "%red%", "%red%" };
1760ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens));
176181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
176281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red", "blue"};
1763ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        expected = new String[] { "%red%", "%red%", "%red%",
176418f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%red%", "%red%", "%blue%", "%blue%",
176518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%blue%", "%blue%","%blue%"};
1766ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens));
176781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
176881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {};
1769ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        expected = new String[] {};
1770ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens));
177181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
177281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
177381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testInstanceSearchQuery() throws Exception {
177481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String[] PROJECTION = new String[] {
177581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.TITLE,                 // 0
177681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_LOCATION,        // 1
177781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.ALL_DAY,               // 2
1778bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden                Instances.CALENDAR_COLOR,        // 3
177981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_TIMEZONE,        // 4
178081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_ID,              // 5
178181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.BEGIN,                 // 6
178281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END,                   // 7
178381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances._ID,                   // 8
178481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.START_DAY,             // 9
178581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END_DAY,               // 10
178681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.START_MINUTE,          // 11
178781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END_MINUTE,            // 12
178881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.HAS_ALARM,             // 13
178981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.RRULE,                 // 14
179081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.RDATE,                 // 15
179181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.SELF_ATTENDEE_STATUS,  // 16
179281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Events.ORGANIZER,                // 17
179381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Events.GUESTS_CAN_MODIFY,        // 18
179481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        };
179581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
17962ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik        String orderBy = CalendarProvider2.SORT_CALENDAR_VIEW;
179781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String where = Instances.SELF_ATTENDEE_STATUS + "!=" +
1798b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED;
179981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
180081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
180181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String START = "2008-05-01T00:00:00";
180281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String END = "2008-05-01T20:00:00";
180381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
180481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event1 = new EventInfo("search orange",
180581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
180681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
180781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
180881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
180981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event1.mDescription = "this is description1";
181081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
181181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event2 = new EventInfo("search purple",
181281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
181381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
181481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
181581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
181681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event2.mDescription = "lasers, out of nowhere";
181781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
181881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event3 = new EventInfo("",
181981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
182081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
182181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
182281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
182381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event3.mDescription = "kapow";
182481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
182581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo[] events = { event1, event2, event3 };
182681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
182781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[0]);
182881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[1]);
182981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[2]);
183081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
183181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        Time time = new Time(DEFAULT_TIMEZONE);
183281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        time.parse3339(START);
183381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        long startMs = time.toMillis(true /* ignoreDst */);
183481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // Query starting from way in the past to one hour into the event.
183581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // Query is more than 2 months so the range won't get extended by the provider.
183681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        Cursor cursor = null;
183781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
183881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
183945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
184081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
184181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
18422ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "search", where, null, orderBy);
184381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(2, cursor.getCount());
184481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
184581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
184681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
184781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
184881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
184981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
185081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
185145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
185281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
185381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
18542ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "purple", where, null, orderBy);
185581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(1, cursor.getCount());
185681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
185781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
185881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
185981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
186081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
186181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
186281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
186345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
186481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
186581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
18662ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "puurple", where, null, orderBy);
186781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(0, cursor.getCount());
186881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
186981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
187081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
187181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
187281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
187381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
187481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
187545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
187681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
187781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
18782ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "purple lasers", where, null, orderBy);
187981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(1, cursor.getCount());
188081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
188181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
188281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
188381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
188481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
188581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
188681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
188745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
188881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
188981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
18902ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "lasers kapow", where, null, orderBy);
189181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(0, cursor.getCount());
189281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
189381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
189481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
189581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
1896dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1897dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1898dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
189945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
1900dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1901dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
19022ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "\"search purple\"", where, null, orderBy);
1903dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(1, cursor.getCount());
1904dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1905dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1906dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1907dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
1908dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1909dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1910dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
191145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
1912dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1913dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
19142ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "\"purple search\"", where, null, orderBy);
1915dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(0, cursor.getCount());
1916dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1917dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1918dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1919dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
1920dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1921dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1922dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
192345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            cursor = queryInstances(mResolver, PROJECTION,
1924dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1925dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
19262ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "%", where, null, orderBy);
1927dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(0, cursor.getCount());
1928dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1929dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1930dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1931dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
193281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
193381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
193481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
193530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff    public void testDeleteCalendar() throws Exception {
193630c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        int calendarId0 = insertCal("Calendar0", DEFAULT_TIMEZONE);
193730c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        int calendarId1 = insertCal("Calendar1", DEFAULT_TIMEZONE, "user2@google.com");
193830c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        insertEvent(calendarId0, mEvents[0]);
193930c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        insertEvent(calendarId1, mEvents[1]);
194030c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 2 calendars and 2 events
1941b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 2);
1942b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 2);
194330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1944b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int deletes = mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
194530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                "ownerAccount='user2@google.com'", null /* selectionArgs */);
194630c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
194730c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(1, deletes);
194830c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 1 calendar and 1 event
1949b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 1);
1950b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 1);
195130c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1952b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        deletes = mResolver.delete(Uri.withAppendedPath(CalendarContract.Calendars.CONTENT_URI,
195330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                String.valueOf(calendarId0)),
195430c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                null /* selection*/ , null /* selectionArgs */);
195530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
195630c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(1, deletes);
195730c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 0 calendars and 0 events
1958b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 0);
1959b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 0);
196030c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1961b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        deletes = mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
196230c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                "ownerAccount=?", new String[] {"user2@google.com"} /* selectionArgs */);
196330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
196430c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(0, deletes);
196530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff    }
1966ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak
1967e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff    public void testCalendarAlerts() throws Exception {
1968e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // This projection is from AlertActivity; want to make sure it works.
1969e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        String[] projection = new String[] {
1970b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts._ID,              // 0
1971b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.TITLE,            // 1
1972b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_LOCATION,   // 2
1973b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALL_DAY,          // 3
1974b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.BEGIN,            // 4
1975b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.END,              // 5
1976b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID,         // 6
1977b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.CALENDAR_COLOR,   // 7
1978b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.RRULE,            // 8
1979b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.HAS_ALARM,        // 9
1980b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.STATE,            // 10
1981b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALARM_TIME,       // 11
1982e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        };
1983e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1984ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        mCalendarId = insertCal("CalendarTestAttendees", DEFAULT_TIMEZONE);
1985ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        String calendarIdString = Integer.toString(mCalendarId);
1986ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        checkEvents(0, mDb, calendarIdString);
1987ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        Uri eventUri = insertEvent(mCalendarId, findEvent("normal0"));
1988ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        checkEvents(1, mDb, calendarIdString);
1989ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        long eventId = ContentUris.parseId(eventUri);
1990ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak
1991ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        Uri alertUri = CalendarContract.CalendarAlerts.insert(mResolver, eventId /* eventId */,
1992e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                2 /* begin */, 3 /* end */, 4 /* alarmTime */, 5 /* minutes */);
1993ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak        CalendarContract.CalendarAlerts.insert(mResolver, eventId /* eventId */,
1994e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                2 /* begin */, 7 /* end */, 8 /* alarmTime */, 9 /* minutes */);
1995e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1996e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Regular query
1997b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI, projection,
1998e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                null /* selection */, null /* selectionArgs */, null /* sortOrder */);
1999e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2000e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(2, cursor.getCount());
2001e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
2002e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2003e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Instance query
2004e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor = mResolver.query(alertUri, projection,
2005e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                null /* selection */, null /* selectionArgs */, null /* sortOrder */);
2006e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2007e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(1, cursor.getCount());
2008e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
2009e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2010e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Grouped by event query
2011b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        cursor = mResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI_BY_INSTANCE,
2012b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                projection, null /* selection */, null /* selectionArgs */, null /* sortOrder */);
2013e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2014e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(1, cursor.getCount());
2015e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
2016e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff    }
2017e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
2018503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    public void testInsertAlertToNonExistentEvent() {
2019503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        Uri alertUri = CalendarContract.CalendarAlerts.insert(mResolver, 1 /* eventId */,
2020503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                2 /* begin */, 3 /* end */, 4 /* alarmTime */, 5 /* minutes */);
2021503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        assertEquals(null, alertUri);
2022503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    }
2023503a798e5f76ecce75607277292bd9a326ba79ecTony Mak
2024503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    public void testInsertReminderToNonExistentEvent() {
2025503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        ContentValues reminder = new ContentValues();
2026503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        reminder.put(CalendarContract.Reminders.MINUTES, 30);
2027503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_EMAIL);
2028503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        reminder.put(CalendarContract.Attendees.EVENT_ID, 1);
2029503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        Uri reminderUri = mResolver.insert(
2030503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                updatedUri(CalendarContract.Reminders.CONTENT_URI, true, DEFAULT_ACCOUNT,
2031503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                        DEFAULT_ACCOUNT_TYPE), reminder);
2032503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        assertEquals(null, reminderUri);
2033503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    }
2034503a798e5f76ecce75607277292bd9a326ba79ecTony Mak
2035503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    public void testInsertAttendeeToNonExistentEvent() {
2036503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        ContentValues attendee = new ContentValues();
2037503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
2038503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
2039503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
2040503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                CalendarContract.Attendees.TYPE_REQUIRED);
2041503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
2042503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                CalendarContract.Attendees.RELATIONSHIP_ORGANIZER);
2043503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.EVENT_ID, 1);
2044503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_IDENTITY, "ID1");
2045503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        attendee.put(CalendarContract.Attendees.ATTENDEE_ID_NAMESPACE, "IDNS1");
2046503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        Uri attendeesUri = mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
2047503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        assertEquals(null, attendeesUri);
2048503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    }
2049503a798e5f76ecce75607277292bd9a326ba79ecTony Mak
2050503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    public void testInsertExtendedPropertyToNonExistentEvent() {
2051503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        ContentValues extended = new ContentValues();
2052503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        extended.put(CalendarContract.ExtendedProperties.NAME, "foo");
2053503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        extended.put(CalendarContract.ExtendedProperties.VALUE, "bar");
2054503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        extended.put(CalendarContract.ExtendedProperties.EVENT_ID, 1);
2055503a798e5f76ecce75607277292bd9a326ba79ecTony Mak
2056503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        Uri extendedUri = mResolver.insert(
2057503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                updatedUri(CalendarContract.ExtendedProperties.CONTENT_URI, true,
2058503a798e5f76ecce75607277292bd9a326ba79ecTony Mak                        DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), extended);
2059503a798e5f76ecce75607277292bd9a326ba79ecTony Mak        assertEquals(null, extendedUri);
2060503a798e5f76ecce75607277292bd9a326ba79ecTony Mak    }
2061503a798e5f76ecce75607277292bd9a326ba79ecTony Mak
2062c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    void checkEvents(int count, SQLiteDatabase db) {
2063c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Cursor cursor = db.query("Events", null, null, null, null, null, null);
2064c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        try {
2065c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            assertEquals(count, cursor.getCount());
2066c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        } finally {
2067c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            cursor.close();
2068c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        }
2069c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    }
2070175d0cd257853813cb258c7406af3bf481a36c10Erik
2071175d0cd257853813cb258c7406af3bf481a36c10Erik    void checkEvents(int count, SQLiteDatabase db, String calendar) {
2072175d0cd257853813cb258c7406af3bf481a36c10Erik        Cursor cursor = db.query("Events", null, Events.CALENDAR_ID + "=?", new String[] {calendar},
2073175d0cd257853813cb258c7406af3bf481a36c10Erik                null, null, null);
2074175d0cd257853813cb258c7406af3bf481a36c10Erik        try {
2075175d0cd257853813cb258c7406af3bf481a36c10Erik            assertEquals(count, cursor.getCount());
2076175d0cd257853813cb258c7406af3bf481a36c10Erik        } finally {
2077175d0cd257853813cb258c7406af3bf481a36c10Erik            cursor.close();
2078175d0cd257853813cb258c7406af3bf481a36c10Erik        }
2079175d0cd257853813cb258c7406af3bf481a36c10Erik    }
2080c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
2081c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
2082c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//    TODO Reenable this when we are ready to work on this
2083c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//
2084c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//    public void testToShowInsertIsSlowForRecurringEvents() throws Exception {
2085c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        mCalendarId = insertCal("CalendarTestToShowInsertIsSlowForRecurringEvents", DEFAULT_TIMEZONE);
2086c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        String calendarIdString = Integer.toString(mCalendarId);
2087c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        long testStart = System.currentTimeMillis();
2088c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//
2089c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        final int testTrials = 100;
2090c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//
2091c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        for (int i = 0; i < testTrials; i++) {
2092c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//            checkEvents(i, mDb, calendarIdString);
2093c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//            long insertStartTime = System.currentTimeMillis();
2094c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//            Uri eventUri = insertEvent(mCalendarId, findEvent("daily0"));
2095c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//            Log.e(TAG, i + ") insertion time " + (System.currentTimeMillis() - insertStartTime));
2096c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        }
2097c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//        Log.e(TAG, " Avg insertion time = " + (System.currentTimeMillis() - testStart)/testTrials);
2098c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan//    }
2099c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
21009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
21019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Test attendee processing
21029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
21039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
21049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testAttendees() throws Exception {
2105175d0cd257853813cb258c7406af3bf481a36c10Erik        mCalendarId = insertCal("CalendarTestAttendees", DEFAULT_TIMEZONE);
2106175d0cd257853813cb258c7406af3bf481a36c10Erik        String calendarIdString = Integer.toString(mCalendarId);
2107175d0cd257853813cb258c7406af3bf481a36c10Erik        checkEvents(0, mDb, calendarIdString);
2108c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        Uri eventUri = insertEvent(mCalendarId, findEvent("normal0"));
2109175d0cd257853813cb258c7406af3bf481a36c10Erik        checkEvents(1, mDb, calendarIdString);
21109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long eventId = ContentUris.parseId(eventUri);
21119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
21129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues attendee = new ContentValues();
2113b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
2114b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
2115b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
2116b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.TYPE_REQUIRED);
2117b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
2118b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.RELATIONSHIP_ORGANIZER);
2119b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, eventId);
2120bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        attendee.put(CalendarContract.Attendees.ATTENDEE_IDENTITY, "ID1");
2121bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        attendee.put(CalendarContract.Attendees.ATTENDEE_ID_NAMESPACE, "IDNS1");
2122b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri attendeesUri = mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
2123b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik
2124b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver.query(CalendarContract.Attendees.CONTENT_URI, null,
21259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "event_id=" + eventId, null, null);
21260739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("Created event is missing - cannot find EventUri = " + eventUri, 1,
21270739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                cursor.getCount());
2128bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        Set<String> attendeeColumns = attendee.keySet();
2129bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        verifyContentValueAgainstCursor(attendee, attendeeColumns, cursor);
21309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
21319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
21329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
2133ab472739446ef9e4a6fdcf9903d6260741d96acfErik Pasternak        // TODO figure out why this test fails. App works fine for this case.
21340739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("Created event is missing - cannot find EventUri = " + eventUri, 1,
21350739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                cursor.getCount());
2136b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int selfColumn = cursor.getColumnIndex(CalendarContract.Events.SELF_ATTENDEE_STATUS);
21379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
21389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long selfAttendeeStatus = cursor.getInt(selfColumn);
2139b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED, selfAttendeeStatus);
21409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
21419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2142bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        // Update status to declined and change identity
2143bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        ContentValues attendeeUpdate = new ContentValues();
2144bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        attendeeUpdate.put(CalendarContract.Attendees.ATTENDEE_IDENTITY, "ID2");
2145bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        attendee.put(CalendarContract.Attendees.ATTENDEE_IDENTITY, "ID2");
2146bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        attendeeUpdate.put(CalendarContract.Attendees.ATTENDEE_STATUS,
2147bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED);
2148b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_STATUS,
2149b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED);
2150bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        mResolver.update(attendeesUri, attendeeUpdate, null, null);
2151bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan
2152bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        // Check in attendees table
2153bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        cursor = mResolver.query(attendeesUri, null, null, null, null);
2154bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        cursor.moveToNext();
2155bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        verifyContentValueAgainstCursor(attendee, attendeeColumns, cursor);
2156bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        cursor.close();
21579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2158bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        // Test that the self status in events table is updated
21599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
21609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
21619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        selfAttendeeStatus = cursor.getInt(selfColumn);
2162b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED, selfAttendeeStatus);
21639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
21649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
21659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Add another attendee
2166b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Dude");
2167b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, "dude@dude.com");
2168b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_STATUS,
2169b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED);
2170b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
21719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2172b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        cursor = mResolver.query(CalendarContract.Attendees.CONTENT_URI, null,
2173c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                "event_id=" + eventId, null, null);
21749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(2, cursor.getCount());
21759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
21769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
21779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
21789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
21799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        selfAttendeeStatus = cursor.getInt(selfColumn);
2180b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED, selfAttendeeStatus);
21819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
21829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
21839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2184bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan    private void verifyContentValueAgainstCursor(ContentValues cv,
2185bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Set<String> keys, Cursor cursor) {
2186bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        cursor.moveToFirst();
2187bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        for (String key : keys) {
2188bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            assertEquals(cv.get(key).toString(),
2189bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                    cursor.getString(cursor.getColumnIndex(key)));
2190bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        }
2191bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        cursor.close();
2192bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan    }
2193bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan
21949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
219534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik     * Test the event's dirty status and clear it.
2196b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik     *
21977e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param eventId event to fetch.
219834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik     * @param wanted the wanted dirty status
21997e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void testAndClearDirty(long eventId, int wanted) {
22017e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Cursor cursor = mResolver.query(
2202b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId),
22037e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null, null, null, null);
22047e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        try {
22057e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("Event count", 1, cursor.getCount());
22067e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.moveToNext();
2207b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            int dirty = cursor.getInt(cursor.getColumnIndex(CalendarContract.Events.DIRTY));
22087e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("dirty flag", wanted, dirty);
22097e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            if (dirty == 1) {
22107e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                // Have to access database directly since provider will set dirty again.
221134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                mDb.execSQL("UPDATE Events SET " + Events.DIRTY + "=0 WHERE _id=" + eventId);
22127e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            }
22137e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } finally {
22147e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.close();
22157e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
22167e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
22177e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22187e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
22197e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test the count of results from a query.
22207e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param uri The URI to query
22217e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param where The where string or null.
22227e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param wanted The number of results wanted.  An assertion is thrown if it doesn't match.
22237e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22247e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void testQueryCount(Uri uri, String where, int wanted) {
22257e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Cursor cursor = mResolver.query(uri, null/* projection */, where, null /* selectionArgs */,
22267e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* sortOrder */);
22277e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        try {
22287e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("query results", wanted, cursor.getCount());
22297e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } finally {
22307e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.close();
22317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
22327e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
22337e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22347e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
22357e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing.
22367e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
22377e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22387e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testDirty() throws Exception {
22397e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        internalTestDirty(false);
22407e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
22417e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
22437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing for updates from a sync adapter.
22447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
22457e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22467e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testDirtyWithSyncAdapter() throws Exception {
22477e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        internalTestDirty(true);
22487e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
22497e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22507e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
2251bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Adds CALLER_IS_SYNCADAPTER to URI if this is a sync adapter operation.  Otherwise,
2252bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * returns the original URI.
22537e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22540739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private Uri updatedUri(Uri uri, boolean syncAdapter, String account, String accountType) {
22557e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        if (syncAdapter) {
22560739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            return addSyncQueryParams(uri, account, accountType);
22577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } else {
22587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            return uri;
22597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
22607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
22617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22627e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
22637e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing either for syncAdapter operations or client operations.
22647e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * The main difference is syncAdapter operations don't set the dirty bit.
22657e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
22667e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void internalTestDirty(boolean syncAdapter) throws Exception {
22677e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
22687e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2269c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long now = System.currentTimeMillis();
2270c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long begin = (now / 1000) * 1000;
2271c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long end = begin + ONE_HOUR_MILLIS;
2272c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Time time = new Time(DEFAULT_TIMEZONE);
2273c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        time.set(begin);
2274c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String startDate = time.format3339(false);
2275c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        time.set(end);
2276c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String endDate = time.format3339(false);
2277c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
2278c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        EventInfo eventInfo = new EventInfo("current", startDate, endDate, false);
2279c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Uri eventUri = insertEvent(mCalendarId, eventInfo);
22807e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22817e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId = ContentUris.parseId(eventUri);
22827e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 1);
22837e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22847e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues attendee = new ContentValues();
2285b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
2286b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
2287b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
2288b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.TYPE_REQUIRED);
2289b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
2290b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.RELATIONSHIP_ORGANIZER);
2291b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, eventId);
22927e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22937e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri attendeeUri = mResolver.insert(
2294b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Attendees.CONTENT_URI, syncAdapter, DEFAULT_ACCOUNT,
22950739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE),
22967e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                attendee);
22977e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2298b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 1);
22997e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues reminder = new ContentValues();
2301b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.MINUTES, 30);
2302b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_EMAIL);
2303b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Attendees.EVENT_ID, eventId);
23047e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23057e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri reminderUri = mResolver.insert(
2306b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Reminders.CONTENT_URI, syncAdapter, DEFAULT_ACCOUNT,
23070739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE), reminder);
23087e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2309b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Reminders.CONTENT_URI, "event_id=" + eventId, 1);
23107e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2311c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long alarmTime = begin + 5 * ONE_MINUTE_MILLIS;
2312c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
23137e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues alert = new ContentValues();
2314b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.BEGIN, begin);
2315b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.END, end);
2316b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.ALARM_TIME, alarmTime);
2317b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.CREATION_TIME, now);
2318b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.RECEIVED_TIME, now);
2319b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.NOTIFY_TIME, now);
2320744fa975b40b24ea7377c0e273f60a7a4d47e2e0RoboErik        alert.put(CalendarContract.CalendarAlerts.STATE,
2321744fa975b40b24ea7377c0e273f60a7a4d47e2e0RoboErik                CalendarContract.CalendarAlerts.STATE_SCHEDULED);
2322b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.MINUTES, 30);
2323b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.EVENT_ID, eventId);
23247e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23257e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri alertUri = mResolver.insert(
2326b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.CalendarAlerts.CONTENT_URI, syncAdapter,
2327b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), alert);
23287e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
23297e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2330b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 1);
23317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23327e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues extended = new ContentValues();
2333b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.NAME, "foo");
2334b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "bar");
2335b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.EVENT_ID, eventId);
23367e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
233758993e879a53f5454b36036da9799550f2ae0814Andy McFadden        Uri extendedUri = null;
233858993e879a53f5454b36036da9799550f2ae0814Andy McFadden        if (syncAdapter) {
233958993e879a53f5454b36036da9799550f2ae0814Andy McFadden            // Only the sync adapter is allowed to modify ExtendedProperties.
234058993e879a53f5454b36036da9799550f2ae0814Andy McFadden            extendedUri = mResolver.insert(
234158993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    updatedUri(CalendarContract.ExtendedProperties.CONTENT_URI, syncAdapter,
234258993e879a53f5454b36036da9799550f2ae0814Andy McFadden                            DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), extended);
234358993e879a53f5454b36036da9799550f2ae0814Andy McFadden            testAndClearDirty(eventId, syncAdapter ? 0 : 1);
234458993e879a53f5454b36036da9799550f2ae0814Andy McFadden            testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI,
2345ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                    "event_id=" + eventId, 1);
234658993e879a53f5454b36036da9799550f2ae0814Andy McFadden        } else {
234758993e879a53f5454b36036da9799550f2ae0814Andy McFadden            // Confirm that inserting as app fails.
234858993e879a53f5454b36036da9799550f2ae0814Andy McFadden            try {
234958993e879a53f5454b36036da9799550f2ae0814Andy McFadden                extendedUri = mResolver.insert(
235058993e879a53f5454b36036da9799550f2ae0814Andy McFadden                        updatedUri(CalendarContract.ExtendedProperties.CONTENT_URI, syncAdapter,
235158993e879a53f5454b36036da9799550f2ae0814Andy McFadden                                DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), extended);
235258993e879a53f5454b36036da9799550f2ae0814Andy McFadden                fail("Only sync adapter should be allowed to insert into ExtendedProperties");
235358993e879a53f5454b36036da9799550f2ae0814Andy McFadden            } catch (IllegalArgumentException iae) {}
235458993e879a53f5454b36036da9799550f2ae0814Andy McFadden        }
23557e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23567e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Now test updates
23577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        attendee = new ContentValues();
2359b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Sam");
23607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23610739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("update", 1, mResolver.update(
23620739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(attendeeUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
23630739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                attendee,
23647e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
23657e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
23667e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2367b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 1);
23687e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23697e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        alert = new ContentValues();
2370744fa975b40b24ea7377c0e273f60a7a4d47e2e0RoboErik        alert.put(CalendarContract.CalendarAlerts.STATE,
2371744fa975b40b24ea7377c0e273f60a7a4d47e2e0RoboErik                CalendarContract.CalendarAlerts.STATE_DISMISSED);
23727e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23730739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("update", 1, mResolver.update(
23740739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(alertUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), alert,
23757e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
23767e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
23777e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2378b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 1);
23797e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23807e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        extended = new ContentValues();
2381b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "baz");
23827e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
238358993e879a53f5454b36036da9799550f2ae0814Andy McFadden        if (syncAdapter) {
238458993e879a53f5454b36036da9799550f2ae0814Andy McFadden            assertEquals("update", 1, mResolver.update(
238558993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    updatedUri(extendedUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
238658993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    extended,
238758993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    null /* where */, null /* selectionArgs */));
238858993e879a53f5454b36036da9799550f2ae0814Andy McFadden            testAndClearDirty(eventId, syncAdapter ? 0 : 1);
238958993e879a53f5454b36036da9799550f2ae0814Andy McFadden            testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI,
2390ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                    "event_id=" + eventId, 1);
239158993e879a53f5454b36036da9799550f2ae0814Andy McFadden        }
23927e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23937e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Now test deletes
23947e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
23957e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        assertEquals("delete", 1, mResolver.delete(
23960739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(attendeeUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
23977e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null, null /* selectionArgs */));
23987e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2399b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 0);
24007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24010739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("delete", 1, mResolver.delete(
24020739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(reminderUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
24037e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
24047e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24057e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2406b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Reminders.CONTENT_URI, "event_id=" + eventId, 0);
24077e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24080739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("delete", 1, mResolver.delete(
24090739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(alertUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
24107e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
24117e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24127e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
24137e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2414b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 0);
24157e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
241658993e879a53f5454b36036da9799550f2ae0814Andy McFadden        if (syncAdapter) {
241758993e879a53f5454b36036da9799550f2ae0814Andy McFadden            assertEquals("delete", 1, mResolver.delete(
241858993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    updatedUri(extendedUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
241958993e879a53f5454b36036da9799550f2ae0814Andy McFadden                    null /* where */, null /* selectionArgs */));
2420205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
242158993e879a53f5454b36036da9799550f2ae0814Andy McFadden            testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2422ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak            testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI, "event_id=" + eventId,
2423ea28dfc327c87b24855f7abd9a48ba9a1b3f43f5Tony Mak                    0);
242458993e879a53f5454b36036da9799550f2ae0814Andy McFadden        }
24257e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
24267e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24277e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
24287e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test calendar deletion
24297e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
24307e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
24317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testCalendarDeletion() throws Exception {
24327e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
24337e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri eventUri = insertEvent(mCalendarId, findEvent("daily0"));
24347e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId = ContentUris.parseId(eventUri);
24357e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 1);
24367e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri eventUri1 = insertEvent(mCalendarId, findEvent("daily1"));
24377e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId1 = ContentUris.parseId(eventUri);
24387e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        assertEquals("delete", 1, mResolver.delete(eventUri1, null, null));
24397e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Calendar has one event and one deleted event
2440b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
24417e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2442b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals("delete", 1, mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
24437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                "_id=" + mCalendarId, null));
24447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Calendar should be deleted
2445b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null, 0);
24467e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Event should be gone
2447b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 0);
2448205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    }
2449205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
2450205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    /**
2451205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff     * Test multiple account support.
2452205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff     */
2453205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    public void testMultipleAccounts() throws Exception {
2454205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2455205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        int calendarId1 = insertCal("Calendar1", DEFAULT_TIMEZONE, "user2@google.com");
2456205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        Uri eventUri0 = insertEvent(mCalendarId, findEvent("daily0"));
245783c55844974ca611a553e704663ed845d84c7930Ken Shirriff        Uri eventUri1 = insertEvent(calendarId1, findEvent("daily1"));
2458205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
2459b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
2460b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri eventsWithAccount = CalendarContract.Events.CONTENT_URI.buildUpon()
2461b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .appendQueryParameter(CalendarContract.EventsEntity.ACCOUNT_NAME, DEFAULT_ACCOUNT)
2462b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .appendQueryParameter(CalendarContract.EventsEntity.ACCOUNT_TYPE,
2463b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        DEFAULT_ACCOUNT_TYPE)
2464205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff                .build();
2465205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        // Only one event for that account
2466205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        testQueryCount(eventsWithAccount, null, 1);
24671ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff
24681ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Test deletion with account and selection
24691ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff
24701ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        long eventId = ContentUris.parseId(eventUri1);
24711ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Wrong account, should not be deleted
24721ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        assertEquals("delete", 0, mResolver.delete(
24730739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(eventsWithAccount, true /* syncAdapter */, DEFAULT_ACCOUNT,
24740739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE),
24751ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff                "_id=" + eventId, null /* selectionArgs */));
2476b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
24771ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Right account, should be deleted
24781ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        assertEquals("delete", 1, mResolver.delete(
2479b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Events.CONTENT_URI, true /* syncAdapter */,
2480b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        "user2@google.com", DEFAULT_ACCOUNT_TYPE),
24811ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff                "_id=" + eventId, null /* selectionArgs */));
2482b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 1);
24837e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
24847e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
24857e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
24869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run commands, wiping instance table at each step.
24879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This tests full instance expansion.
24889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
24899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
24909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testCommandSequences1() throws Exception {
24919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commandSequences(true);
24929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
24939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
24959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run commands normally.
24969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This tests incremental instance expansion.
24979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
24989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
24999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testCommandSequences2() throws Exception {
25009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commandSequences(false);
25019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
25029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
25049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run thorough set of command sequences
25059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param wipe true if instances should be wiped and regenerated
25069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
25079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
25089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void commandSequences(boolean wipe) throws Exception {
25099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
25109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
25119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mWipe = wipe; // Set global flag
25129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
25149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
25169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
25179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
25189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Command[] commands;
25199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Normal insert/delete");
25219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mNormalInsertDelete;
25229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "All-day insert/delete");
25299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mAlldayInsertDelete;
25309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Recurring insert/delete");
25379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mRecurringInsertDelete;
25389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with truncated recurrence");
25459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithTruncatedRecurrence;
25469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with moved recurrence");
25539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithMovedRecurrence;
25549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with cancel");
25619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mCancelInstance;
25629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with moved recurrence2");
25699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithMovedRecurrence2;
25709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
25759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with no recurrence");
25779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithNoRecurrence;
25789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
25799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
25809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
25819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
25829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
25839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
25849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Test Time toString.
25859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
25869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
25879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // Suppressed because toString currently hangs.
25889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Suppress
25899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testTimeToString() throws Exception {
25909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Time time = new Time(Time.TIMEZONE_UTC);
25919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String str = "2039-01-01T23:00:00.000Z";
25929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String result = "20390101T230000UTC(0,0,0,-1,0)";
25939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        time.parse3339(str);
25949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(result, time.toString());
25959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
25969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2597c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    /**
2598c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     * Test the query done by Event.loadEvents
2599bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Also test that instance queries work when an event straddles the expansion range
2600c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     * @throws Exception
2601c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     */
2602c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    public void testInstanceQuery() throws Exception {
2603c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        final String[] PROJECTION = new String[] {
2604c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.TITLE,                 // 0
2605c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_LOCATION,        // 1
2606c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.ALL_DAY,               // 2
2607bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden                Instances.CALENDAR_COLOR,        // 3
2608c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_TIMEZONE,        // 4
2609c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_ID,              // 5
2610c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.BEGIN,                 // 6
2611c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END,                   // 7
2612c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances._ID,                   // 8
2613c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.START_DAY,             // 9
2614c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END_DAY,               // 10
2615c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.START_MINUTE,          // 11
2616c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END_MINUTE,            // 12
2617c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.HAS_ALARM,             // 13
2618c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.RRULE,                 // 14
2619c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.RDATE,                 // 15
2620c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.SELF_ATTENDEE_STATUS,  // 16
2621c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Events.ORGANIZER,                // 17
2622c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Events.GUESTS_CAN_MODIFY,        // 18
2623c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        };
2624c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
26252ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik        String orderBy = CalendarProvider2.SORT_CALENDAR_VIEW;
2626b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        String where = Instances.SELF_ATTENDEE_STATUS + "!="
2627b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED;
2628c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
2629975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2630975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        final String START = "2008-05-01T00:00:00";
2631975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        final String END = "2008-05-01T20:00:00";
2632975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2633975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        EventInfo[] events = { new EventInfo("normal0",
2634975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                START,
2635975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                END,
2636975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                false /* allDay */,
2637975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                DEFAULT_TIMEZONE) };
2638975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2639975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        insertEvent(calId, events[0]);
2640975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2641975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        Time time = new Time(DEFAULT_TIMEZONE);
2642975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        time.parse3339(START);
2643975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        long startMs = time.toMillis(true /* ignoreDst */);
2644975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Query starting from way in the past to one hour into the event.
2645975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Query is more than 2 months so the range won't get extended by the provider.
264645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        Cursor cursor = queryInstances(mResolver, PROJECTION,
2647975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                startMs - DateUtils.YEAR_IN_MILLIS, startMs + DateUtils.HOUR_IN_MILLIS,
26482ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                where, null, orderBy);
2649975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        try {
2650975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            assertEquals(1, cursor.getCount());
2651975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        } finally {
2652975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            cursor.close();
2653975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        }
2654975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2655975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Now expand the instance range.  The event overlaps the new part of the range.
265645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        cursor = queryInstances(mResolver, PROJECTION,
2657975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                startMs - DateUtils.YEAR_IN_MILLIS, startMs + 2 * DateUtils.HOUR_IN_MILLIS,
26582ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                where, null, orderBy);
2659975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        try {
2660975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            assertEquals(1, cursor.getCount());
2661975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        } finally {
2662975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            cursor.close();
2663975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        }
2664c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    }
2665c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
266645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    /**
266745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * Performs a query to return all visible instances in the given range that
266845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * match the given selection. This is a blocking function and should not be
266945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * done on the UI thread. This will cause an expansion of recurring events
267045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * to fill this time range if they are not already expanded and will slow
267145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * down for larger time ranges with many recurring events.
267245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     *
267345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param cr The ContentResolver to use for the query
267445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param projection The columns to return
267545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param begin The start of the time range to query in UTC millis since
267645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     *            epoch
267745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param end The end of the time range to query in UTC millis since epoch
267845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param selection Filter on the query as an SQL WHERE statement
267945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param selectionArgs Args to replace any '?'s in the selection
268045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param orderBy How to order the rows as an SQL ORDER BY statement
268145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @return A Cursor of instances matching the selection
268245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     */
268345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    private static final Cursor queryInstances(ContentResolver cr, String[] projection, long begin,
268445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            long end, String selection, String[] selectionArgs, String orderBy) {
268545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik
268645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
268745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        ContentUris.appendId(builder, begin);
268845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        ContentUris.appendId(builder, end);
268945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        if (TextUtils.isEmpty(selection)) {
269045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selection = WHERE_CALENDARS_SELECTED;
269145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selectionArgs = WHERE_CALENDARS_ARGS;
269245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        } else {
269345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
269445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            if (selectionArgs != null && selectionArgs.length > 0) {
269545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
269645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs[selectionArgs.length - 1] = WHERE_CALENDARS_ARGS[0];
269745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            } else {
269845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs = WHERE_CALENDARS_ARGS;
269945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            }
270045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        }
270145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        return cr.query(builder.build(), projection, selection, selectionArgs,
270245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
270345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    }
270445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik
270545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    /**
270645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * Performs a query to return all visible instances in the given range that
270745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * match the given selection. This is a blocking function and should not be
270845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * done on the UI thread. This will cause an expansion of recurring events
270945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * to fill this time range if they are not already expanded and will slow
271045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * down for larger time ranges with many recurring events.
271145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     *
271245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param cr The ContentResolver to use for the query
271345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param projection The columns to return
271445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param begin The start of the time range to query in UTC millis since
271545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     *            epoch
271645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param end The end of the time range to query in UTC millis since epoch
271745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param searchQuery A string of space separated search terms. Segments
271845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     *            enclosed by double quotes will be treated as a single term.
271945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param selection Filter on the query as an SQL WHERE statement
272045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param selectionArgs Args to replace any '?'s in the selection
272145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @param orderBy How to order the rows as an SQL ORDER BY statement
272245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     * @return A Cursor of instances matching the selection
272345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik     */
272445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    public static final Cursor queryInstances(ContentResolver cr, String[] projection, long begin,
272545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            long end, String searchQuery, String selection, String[] selectionArgs, String orderBy)
272645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            {
272745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        Uri.Builder builder = Instances.CONTENT_SEARCH_URI.buildUpon();
272845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        ContentUris.appendId(builder, begin);
272945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        ContentUris.appendId(builder, end);
273045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        builder = builder.appendPath(searchQuery);
273145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        if (TextUtils.isEmpty(selection)) {
273245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selection = WHERE_CALENDARS_SELECTED;
273345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selectionArgs = WHERE_CALENDARS_ARGS;
273445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        } else {
273545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
273645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            if (selectionArgs != null && selectionArgs.length > 0) {
273745f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
273845f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs[selectionArgs.length - 1] = WHERE_CALENDARS_ARGS[0];
273945f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            } else {
274045f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                selectionArgs = WHERE_CALENDARS_ARGS;
274145f18d759c5f45a856e1ab709856d5d238d4468fRoboErik            }
274245f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        }
274345f18d759c5f45a856e1ab709856d5d238d4468fRoboErik        return cr.query(builder.build(), projection, selection, selectionArgs,
274445f18d759c5f45a856e1ab709856d5d238d4468fRoboErik                orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
274545f18d759c5f45a856e1ab709856d5d238d4468fRoboErik    }
274645f18d759c5f45a856e1ab709856d5d238d4468fRoboErik
27479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Cursor queryInstances(long begin, long end) {
2748b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri url = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_URI, begin + "/" + end);
27499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mResolver.query(url, null, null, null, null);
27509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
27519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected static class MockProvider extends ContentProvider {
27539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        private String mAuthority;
27559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        private int mNumItems = 0;
27579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public MockProvider(String authority) {
27599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAuthority = authority;
27609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public boolean onCreate() {
27649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return true;
27659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Cursor query(Uri uri, String[] projection, String selection,
27699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String[] selectionArgs, String sortOrder) {
2770aaa7f0ddf94d402075572b43f39f1866407fbb3fJeff Brown            return new MatrixCursor(new String[]{ "_id" }, 0);
27719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public String getType(Uri uri) {
27759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            throw new UnsupportedOperationException();
27769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Uri insert(Uri uri, ContentValues values) {
27809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mNumItems++;
27819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return Uri.parse("content://" + mAuthority + "/" + mNumItems);
27829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public int delete(Uri uri, String selection, String[] selectionArgs) {
27869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return 0;
27879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
27899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
27909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public int update(Uri uri, ContentValues values, String selection,
27919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String[] selectionArgs) {
27929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return 0;
27939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
27949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2795ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2796ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void cleanCalendarDataTable(SQLiteOpenHelper helper) {
2797ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        if (null == helper) {
2798ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            return;
2799ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2800ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        SQLiteDatabase db = helper.getWritableDatabase();
2801ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        db.execSQL("DELETE FROM CalendarCache;");
2802ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2803ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2804ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    public void testGetAndSetTimezoneDatabaseVersion() throws CalendarCache.CacheException {
2805ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2806ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cleanCalendarDataTable(helper);
2807ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2808ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2809ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        boolean hasException = false;
2810ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        try {
2811ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            String value = cache.readData(null);
2812ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        } catch (CalendarCache.CacheException e) {
2813ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            hasException = true;
2814ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2815ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertTrue(hasException);
2816ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2817ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertNull(cache.readTimezoneDatabaseVersion());
2818ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2819ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cache.writeTimezoneDatabaseVersion("1234");
2820ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals("1234", cache.readTimezoneDatabaseVersion());
2821ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2822ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cache.writeTimezoneDatabaseVersion("5678");
2823ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals("5678", cache.readTimezoneDatabaseVersion());
2824ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2825ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2826ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void checkEvent(int eventId, String title, long dtStart, long dtEnd, boolean allDay) {
2827b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri uri = Uri.parse("content://" + CalendarContract.AUTHORITY + "/events");
2828ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Log.i(TAG, "Looking for EventId = " + eventId);
2829ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2830ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Cursor cursor = mResolver.query(uri, null, null, null, null);
2831ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(1, cursor.getCount());
2832ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2833b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexTitle = cursor.getColumnIndex(CalendarContract.Events.TITLE);
2834b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexDtStart = cursor.getColumnIndex(CalendarContract.Events.DTSTART);
2835b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexDtEnd = cursor.getColumnIndex(CalendarContract.Events.DTEND);
2836b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexAllDay = cursor.getColumnIndex(CalendarContract.Events.ALL_DAY);
2837ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        if (!cursor.moveToNext()) {
2838ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            Log.e(TAG,"Could not find inserted event");
2839ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            assertTrue(false);
2840ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2841ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(title, cursor.getString(colIndexTitle));
2842ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(dtStart, cursor.getLong(colIndexDtStart));
2843ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(dtEnd, cursor.getLong(colIndexDtEnd));
2844ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(allDay, (cursor.getInt(colIndexAllDay) != 0));
2845ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cursor.close();
2846ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2847ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2848ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    public void testChangeTimezoneDB() {
2849ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2850ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2851b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver
2852b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .query(CalendarContract.Events.CONTENT_URI, null, null, null, null);
2853ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(0, cursor.getCount());
2854ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cursor.close();
2855ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2856ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        EventInfo[] events = { new EventInfo("normal0",
2857ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        "2008-05-01T00:00:00",
2858ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        "2008-05-02T00:00:00",
2859ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        false,
2860ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        DEFAULT_TIMEZONE) };
2861ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2862ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Uri uri = insertEvent(calId, events[0]);
2863ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertNotNull(uri);
2864ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2865ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // check the inserted event
2866ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        checkEvent(1, events[0].mTitle, events[0].mDtstart, events[0].mDtend, events[0].mAllDay);
2867ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2868ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // inject a new time zone
2869ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        getProvider().doProcessEventRawTimes(TIME_ZONE_AMERICA_ANCHORAGE,
2870ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                MOCK_TIME_ZONE_DATABASE_VERSION);
2871ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2872ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // check timezone database version
2873ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(MOCK_TIME_ZONE_DATABASE_VERSION, getProvider().getTimezoneDatabaseVersion());
2874ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
28753443e3ebeaa39e8415b43e7cf3b218caee554e9bFabrice Di Meglio        // check that the inserted event has *not* been updated
28763443e3ebeaa39e8415b43e7cf3b218caee554e9bFabrice Di Meglio        checkEvent(1, events[0].mTitle, events[0].mDtstart, events[0].mDtend, events[0].mAllDay);
2877ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2878315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2879315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public static final Uri PROPERTIES_CONTENT_URI =
2880b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            Uri.parse("content://" + CalendarContract.AUTHORITY + "/properties");
2881315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2882315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testGetProviderProperties() throws CalendarCache.CacheException {
2883315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2884315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2885315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2886315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2887315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2888315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Denver");
2889315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Los_Angeles");
2890315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2891315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2892315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Cursor cursor = mResolver.query(PROPERTIES_CONTENT_URI, null, null, null, null);
2893315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(4, cursor.getCount());
2894315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
289552747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka        final int keyColumnIndex = cursor.getColumnIndex(CalendarCache.COLUMN_NAME_KEY);
289652747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka        final int valueColumnIndex = cursor.getColumnIndex(CalendarCache.COLUMN_NAME_VALUE);
2897315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Map<String, String> map = new HashMap<String, String>();
2898315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2899315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        while (cursor.moveToNext()) {
290052747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka            String key = cursor.getString(keyColumnIndex);
290152747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka            String value = cursor.getString(valueColumnIndex);
2902315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            map.put(key, value);
2903315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        }
2904315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2905315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_DATABASE_VERSION));
2906315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_TYPE));
2907315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_INSTANCES));
2908315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS));
2909315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2910315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("2010k", map.get(CalendarCache.KEY_TIMEZONE_DATABASE_VERSION));
2911315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("America/Denver", map.get(CalendarCache.KEY_TIMEZONE_INSTANCES));
2912315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("America/Los_Angeles", map.get(CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS));
2913315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(CalendarCache.TIMEZONE_TYPE_AUTO, map.get(CalendarCache.KEY_TIMEZONE_TYPE));
2914315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2915315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cursor.close();
2916315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2917315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2918315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testGetProviderPropertiesByKey() throws CalendarCache.CacheException {
2919315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2920315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2921315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2922315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2923315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2924315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Denver");
2925315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Los_Angeles");
2926315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2927315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2928315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(CalendarCache.TIMEZONE_TYPE_AUTO, CalendarCache.KEY_TIMEZONE_TYPE);
2929315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("2010k", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2930315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES);
2931315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Los_Angeles", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2932315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2933315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2934315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void checkValueForKey(String value, String key) {
2935315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Cursor cursor = mResolver.query(PROPERTIES_CONTENT_URI, null,
2936315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "key=?", new String[] {key}, null);
2937315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2938315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(1, cursor.getCount());
2939315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(cursor.moveToFirst());
294052747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka        assertEquals(cursor.getString(cursor.getColumnIndex(CalendarCache.COLUMN_NAME_KEY)),
294152747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka                key);
294252747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka        assertEquals(cursor.getString(cursor.getColumnIndex(CalendarCache.COLUMN_NAME_VALUE)),
294352747f6fd653498300af7b796b07679eb6b48998Sudheer Shanka                value);
2944315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2945315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cursor.close();
2946315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2947315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2948315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testUpdateProviderProperties() throws CalendarCache.CacheException {
2949315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2950315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2951315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2952315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2953315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String localTimezone = TimeZone.getDefault().getID();
2954315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2955315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial value
2956315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2957315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2958315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey("2009s", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2959315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("2009s", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2960315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2961315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial values
2962315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2963315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Chicago");
2964315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Denver");
2965315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2966315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(CalendarCache.TIMEZONE_TYPE_AUTO, CalendarCache.KEY_TIMEZONE_TYPE);
2967315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2968315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2969315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2970315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(CalendarCache.TIMEZONE_TYPE_HOME, CalendarCache.KEY_TIMEZONE_TYPE);
2971315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES);
2972315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2973315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2974315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial value
2975315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("");
2976315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2977315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2978315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2979315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2980315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2981315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void updateValueForKey(String value, String key) {
2982315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        ContentValues contentValues = new ContentValues();
2983315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        contentValues.put(CalendarCache.COLUMN_NAME_VALUE, value);
2984315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2985315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        int result = mResolver.update(PROPERTIES_CONTENT_URI,
2986315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                contentValues,
2987315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + "=?",
2988315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                new String[] {key});
2989315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2990315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(1, result);
2991315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
29928ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
2993bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
2994bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Verifies that the number of defined calendars meets expectations.
2995bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     *
2996bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * @param expectedCount The number of calendars we expect to find.
2997bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
299874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarCount(int expectedCount) {
299974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        Cursor cursor = mResolver.query(mCalendarsUri,
300074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* projection */,
300174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selection */,
300274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selectionArgs */,
300374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* sortOrder */);
300474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertEquals(expectedCount, cursor.getCount());
300574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        cursor.close();
300674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
300774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
300874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarExists(int calId) {
300974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertTrue(isCalendarExists(calId));
301074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
301174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
301274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarDoesNotExists(int calId) {
301374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertFalse(isCalendarExists(calId));
301474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
301574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
301674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private boolean isCalendarExists(int calId) {
301774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        Cursor cursor = mResolver.query(mCalendarsUri,
301874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] {Calendars._ID},
301974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selection */,
302074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selectionArgs */,
302174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* sortOrder */);
302274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        boolean found = false;
302374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        while (cursor.moveToNext()) {
302474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio            if (calId == cursor.getInt(0)) {
302574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                found = true;
302674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                break;
302774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio            }
302874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        }
302974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        cursor.close();
303074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        return found;
303174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
303274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
303374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteAllCalendars() {
303474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
303574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
303674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        insertCal("Calendar1", "America/Los_Angeles");
303774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        insertCal("Calendar2", "America/Los_Angeles");
303874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
303974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
304074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
304174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(null /* selection */, null /* selectionArgs*/);
304274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
304374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
304474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
304574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteCalendarsWithSelection() {
304674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
304774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
304874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId1 = insertCal("Calendar1", "America/Los_Angeles");
304974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId2 = insertCal("Calendar2", "America/Los_Angeles");
305074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
305174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
305274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
305374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId2);
305474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
305574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=" + calId2, null /* selectionArgs*/);
305674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(1);
305774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
305874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarDoesNotExists(calId2);
305974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
306074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
306174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteCalendarsWithSelectionAndArgs() {
306274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
306374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
306474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId1 = insertCal("Calendar1", "America/Los_Angeles");
306574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId2 = insertCal("Calendar2", "America/Los_Angeles");
306674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
306774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
306874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
306974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId2);
307074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
307174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=?",
307274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] { Integer.toString(calId2) });
307374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(1);
307474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
307574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarDoesNotExists(calId2);
307674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
307774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=?" + " AND " + Calendars.NAME + "=?",
307874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] { Integer.toString(calId1), "Calendar1" });
307974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
308074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
308108007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung
308208007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung    public void testGetColumnIndex_IsPrimary() {
308308007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        checkCalendarCount(0);
308408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        int calendarId0 = insertCal("Calendar0", DEFAULT_TIMEZONE);
308508007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung
308608007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String[] projection = new String[] {
308708007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            Calendars.ACCOUNT_NAME,
308808007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            Calendars.CALENDAR_DISPLAY_NAME,
308908007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            Calendars.OWNER_ACCOUNT,
309008007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            Calendars.IS_PRIMARY
309108007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        };
309208007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String selection = "((" + Calendars.ACCOUNT_NAME + " = ? ))";
309308007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String[] selectionArgs = new String[] {
309408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            DEFAULT_ACCOUNT
309508007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        };
309608007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        Cursor cursor = mResolver.query(Calendars.CONTENT_URI, projection, selection, selectionArgs,
309708007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung                null);
309808007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        assertNotNull(cursor);
309908007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        assertEquals(3, cursor.getColumnIndex(Calendars.IS_PRIMARY));
310008007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        cursor.close();
310108007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        deleteMatchingCalendars(Calendars._ID + "=" + calendarId0, null /* selectionArgs*/);
310208007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        checkCalendarCount(0);
310308007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung    }
310408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung
310508007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung    public void testGetColumnIndex_Count() {
310608007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        checkCalendarCount(0);
310708007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        int calendarId0 = insertCal("Calendar0", DEFAULT_TIMEZONE);
310808007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung
310908007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String[] projection = new String[] {
311008007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            BaseColumns._COUNT
311108007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        };
311208007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String selection = "((" + Calendars.ACCOUNT_NAME + " = ? ))";
311308007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        String[] selectionArgs = new String[] {
311408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung            DEFAULT_ACCOUNT
311508007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        };
311608007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        Cursor cursor = mResolver.query(Calendars.CONTENT_URI, projection, selection, selectionArgs,
311708007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung                null);
311808007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        assertNotNull(cursor);
311908007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        assertEquals(0, cursor.getColumnIndex(BaseColumns._COUNT));
312008007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        cursor.close();
312108007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        deleteMatchingCalendars(Calendars._ID + "=" + calendarId0, null /* selectionArgs*/);
312208007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung        checkCalendarCount(0);
312308007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung    }
312408007188ce3af03ed13e9252febc9b22e1bfe953Keith Cheung
31259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff}
3126