CalendarProvider2Test.java revision b9644fe24edf9e25f0b21c1394e88d25070e0238
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
19ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erikimport com.android.common.ArrayListCursor;
20ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
2181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ComponentName;
2281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentProvider;
2381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentUris;
2481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.ContentValues;
2581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.Context;
2681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.Entity;
2781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.EntityIterator;
2881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.Intent;
2981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.content.res.Resources;
309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.Cursor;
319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteDatabase;
3281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.database.sqlite.SQLiteOpenHelper;
339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.net.Uri;
34b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract;
35b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Calendars;
36b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Events;
37b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.EventsEntity;
38b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Instances;
3981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.AndroidTestCase;
4081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.IsolatedContext;
4181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.RenamingDelegatingContext;
429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.test.mock.MockContentResolver;
4381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.mock.MockContext;
4481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.suitebuilder.annotation.SmallTest;
4581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.test.suitebuilder.annotation.Smoke;
469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.test.suitebuilder.annotation.Suppress;
4781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.text.format.DateUtils;
4881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport android.text.format.Time;
499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.util.Log;
5081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
5181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport java.io.File;
529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport java.util.ArrayList;
5381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangimport java.util.Arrays;
54315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.HashMap;
55315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.Map;
56315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.TimeZone;
579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/**
599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Runs various tests on an isolated Calendar provider with its own database.
6025e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio *
6125e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * You can run the tests with the following command line:
6225e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio *
6325e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * adb shell am instrument
6425e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -e debug false
6525e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -w
6625e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * -e class com.android.providers.calendar.CalendarProvider2Test
6725e5cdec4e39982fedcce0733d2b8ad1aa665b19Fabrice Di Meglio * com.android.providers.calendar.tests/android.test.InstrumentationTestRunner
6881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang *
6981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * This test no longer extends ProviderTestCase2 because it actually doesn't
7081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * allow you to inject a custom context (which we needed to mock out the calls
7181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * to start a service). We the next best thing, which is copy the relevant code
7281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang * from PTC2 and extend AndroidTestCase instead.
739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
7473e55ee06fd7c595495d0ed8971a5dae36fb0399Brett Chabot// flaky test, add back to LargeTest when fixed - bug 2395696
7573e55ee06fd7c595495d0ed8971a5dae36fb0399Brett Chabot// @LargeTest
7681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tangpublic class CalendarProvider2Test extends AndroidTestCase {
779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    static final String TAG = "calendar";
789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
790739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private static final String DEFAULT_ACCOUNT_TYPE = "com.google";
800739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private static final String DEFAULT_ACCOUNT = "joe@joe.com";
810739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik
8281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    private CalendarProvider2ForTesting mProvider;
839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private SQLiteDatabase mDb;
849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private MetaData mMetaData;
859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Context mContext;
869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private MockContentResolver mResolver;
8719fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana    private Uri mEventsUri = Events.CONTENT_URI;
8874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private Uri mCalendarsUri = Calendars.CONTENT_URI;
899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int mCalendarId;
909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected boolean mWipe = false;
92e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    protected boolean mForceDtend = false;
939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // We need a unique id to put in the _sync_id field so that we can create
959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // recurrence exceptions that refer to recurring events.
969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int mGlobalSyncId = 1000;
979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static final String CALENDAR_URL =
987e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            "http://www.google.com/calendar/feeds/joe%40joe.com/private/full";
999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
100ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String TIME_ZONE_AMERICA_ANCHORAGE = "America/Anchorage";
101ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String TIME_ZONE_AMERICA_LOS_ANGELES = "America/Los_Angeles";
102ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String DEFAULT_TIMEZONE = TIME_ZONE_AMERICA_LOS_ANGELES;
103ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
104ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private static final String MOCK_TIME_ZONE_DATABASE_VERSION = "2010a";
105ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
106c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_MINUTE_MILLIS = 60*1000;
107c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_HOUR_MILLIS = 3600*1000;
108c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private static final long ONE_WEEK_MILLIS = 7 * 24 * 3600 * 1000;
10981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
11081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    /**
11181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang     * We need a few more stub methods so that our tests can run
11281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang     */
11381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected class MockContext2 extends MockContext {
11481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
11581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
11681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public String getPackageName() {
11781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getPackageName();
11881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
11981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
12081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
12181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public Resources getResources() {
12281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getResources();
12381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
12481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
12581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
12681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public File getDir(String name, int mode) {
12781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            // name the directory so the directory will be seperated from
12881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            // one created through the regular Context
12981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return getContext().getDir("mockcontext2_" + name, mode);
13081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
13181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
13281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
13381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public ComponentName startService(Intent service) {
13481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return null;
13581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
13681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
13781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        @Override
13881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        public boolean stopService(Intent service) {
13981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            return false;
14081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
14181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
14281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
1439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * KeyValue is a simple class that stores a pair of strings representing
1459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * a (key, value) pair.  This is used for updating events.
1469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class KeyValue {
1489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String key;
1499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String value;
1509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public KeyValue(String key, String value) {
1529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.key = key;
1539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.value = value;
1549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
1569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * A generic command interface.  This is used to support a sequence of
1599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * commands that can create events, delete or update events, and then
1609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * check that the state of the database is as expected.
1619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private interface Command {
1639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute();
1649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
1659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to insert a new event into the database.  The event is
1689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * specified by its name (or "title").  All of the event fields (the
1699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * start and end time, whether it is an all-day event, and so on) are
1709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * stored in a separate table (the "mEvents" table).
1719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Insert implements Command {
1739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        EventInfo eventInfo;
1749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Insert(String eventName) {
1769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            eventInfo = findEvent(eventName);
1779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
1809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "insert " + eventInfo.mTitle);
1819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            insertEvent(mCalendarId, eventInfo);
1829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
1839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
1849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
1869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to delete an event, specified by the event name.
1879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
1889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Delete implements Command {
1899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String eventName;
1900739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        String account;
1910739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        String accountType;
1929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
1939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1940739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        public Delete(String eventName, int expected, String account, String accountType) {
1959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.eventName = eventName;
1969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
1970739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            this.account = account;
1980739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            this.accountType = accountType;
1999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "delete " + eventName);
2030739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            int rows = deleteMatchingEvents(eventName, account, accountType);
2049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, rows);
2059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is used to update an event.  The values to update are specified
2109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * with an array of (key, value) pairs.  Both the key and value are
2119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * specified as strings.  Event fields that are not really strings (such
2129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * as DTSTART which is a long) should be converted to the appropriate type
2139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * but that isn't supported yet.  When needed, that can be added here
2149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * by checking for specific keys and converting the associated values.
2159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class Update implements Command {
2179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String eventName;
2189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        KeyValue[] pairs;
2199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Update(String eventName, KeyValue[] pairs) {
2219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.eventName = eventName;
2229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.pairs = pairs;
2239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "update " + eventName);
2279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (mWipe) {
2289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Wipe instance table so it will be regenerated
2299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mMetaData.clearInstanceRange();
2309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
2319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            ContentValues map = new ContentValues();
2329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (KeyValue pair : pairs) {
2339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String value = pair.value;
234b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                if (CalendarContract.Events.STATUS.equals(pair.key)) {
2359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    // Do type conversion for STATUS
2369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    map.put(pair.key, Integer.parseInt(value));
2379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                } else {
2389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    map.put(pair.key, value);
2399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
2409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
241ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            if (map.size() == 1 && map.containsKey(Events.STATUS)) {
242ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                updateMatchingEventsStatusOnly(eventName, map);
243ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            } else {
244ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                updateMatchingEvents(eventName, map);
245ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            }
2469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command queries the number of events and compares it to the given
2519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expected value.
2529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class QueryNumEvents implements Command {
2549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
2559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public QueryNumEvents(int expected) {
2579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
2589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = mResolver.query(mEventsUri, null, null, null, null);
2629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, cursor.getCount());
2639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
2649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command dumps the list of events to the log for debugging.
2709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class DumpEvents implements Command {
2729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public DumpEvents() {
2749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = mResolver.query(mEventsUri, null, null, null, null);
2789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dumpCursor(cursor);
2799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
2809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
2849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command dumps the list of instances to the log for debugging.
2859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
2869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class DumpInstances implements Command {
2879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
2889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
2899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public DumpInstances(String startDate, String endDate) {
2919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
2929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
2939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
2949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
2959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
2969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
2979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
2999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dumpCursor(cursor);
3019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
3029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This command queries the number of instances and compares it to the given
3079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expected value.
3089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class QueryNumInstances implements Command {
3109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int expected;
3119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
3129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
3139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public QueryNumInstances(String startDate, String endDate, int expected) {
3159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
3169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
3179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
3189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
3199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
3209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.expected = expected;
3219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
3249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(expected, cursor.getCount());
3269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
3279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * When this command runs it verifies that all of the instances in the
3329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * given range match the expected instances (each instance is specified by
3339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * a start date).
3349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * If you just want to verify that an instance exists in a given date
3359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * range, use {@link VerifyInstance} instead.
3369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class VerifyAllInstances implements Command {
3389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long[] instances;
3399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
3409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
3419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public VerifyAllInstances(String startDate, String endDate, String[] dates) {
3439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
3449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
3459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
3469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
3479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
3489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (dates == null) {
3509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return;
3519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Convert all the instance date strings to UTC milliseconds
3549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int len = dates.length;
3559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            this.instances = new long[len];
3569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int index = 0;
3579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (String instance : dates) {
3589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.parse3339(instance);
3599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                this.instances[index++] = time.toMillis(false /* use isDst */);
3609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
3649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
3659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int len = 0;
3669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instances != null) {
3679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                len = instances.length;
3689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (len != cursor.getCount()) {
3709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                dumpCursor(cursor);
3719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals("number of instances don't match", len, cursor.getCount());
3739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instances == null) {
3759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return;
3769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
3779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int beginColumn = cursor.getColumnIndex(Instances.BEGIN);
3799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (cursor.moveToNext()) {
3809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long begin = cursor.getLong(beginColumn);
3819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Search the list of expected instances for a matching start
3839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // time.
3849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean found = false;
3859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                for (long instance : instances) {
3869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    if (instance == begin) {
3879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        found = true;
3889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
3899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    }
3909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
3919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!found) {
3929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int titleColumn = cursor.getColumnIndex(Events.TITLE);
3939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int allDayColumn = cursor.getColumnIndex(Events.ALL_DAY);
3949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String title = cursor.getString(titleColumn);
3969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    boolean allDay = cursor.getInt(allDayColumn) != 0;
3979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE |
3989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            DateUtils.FORMAT_24HOUR;
3999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    if (allDay) {
4009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        flags |= DateUtils.FORMAT_UTC;
4019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    } else {
4029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        flags |= DateUtils.FORMAT_SHOW_TIME;
4039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    }
4049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String date = DateUtils.formatDateRange(mContext, begin, begin, flags);
4059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    String mesg = String.format("Test failed!"
4069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            + " unexpected instance (\"%s\") at %s",
4079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            title, date);
4089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    Log.e(TAG, mesg);
4099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!found) {
4119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    dumpCursor(cursor);
4129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                assertTrue(found);
4149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
4169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
4189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
4209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * When this command runs it verifies that the given instance exists in
4219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * the given date range.
4229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
4239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class VerifyInstance implements Command {
4249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long instance;
4259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        boolean allDay;
4269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin;
4279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long end;
4289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        /**
4309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * Creates a command to check that the given range [startDate,endDate]
4319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * contains a specific instance of an event (specified by "date").
4329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         *
4339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param startDate the beginning of the date range
4349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param endDate the end of the date range
4359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         * @param date the date or date-time string of an event instance
4369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff         */
4379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public VerifyInstance(String startDate, String endDate, String date) {
4389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(DEFAULT_TIMEZONE);
4399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
4409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            begin = time.toMillis(false /* use isDst */);
4419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
4429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            end = time.toMillis(false /* use isDst */);
4439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Convert the instance date string to UTC milliseconds
4459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(date);
4469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            allDay = time.allDay;
4479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            instance = time.toMillis(false /* use isDst */);
4489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void execute() {
4519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Cursor cursor = queryInstances(begin, end);
4529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            int beginColumn = cursor.getColumnIndex(Instances.BEGIN);
4539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            boolean found = false;
4549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (cursor.moveToNext()) {
4559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long begin = cursor.getLong(beginColumn);
4569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (instance == begin) {
4589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    found = true;
4599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    break;
4609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (!found) {
4639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE;
4649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (allDay) {
4659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    flags |= DateUtils.FORMAT_UTC;
4669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                } else {
4679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    flags |= DateUtils.FORMAT_SHOW_TIME;
4689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
4699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String date = DateUtils.formatDateRange(mContext, instance, instance, flags);
4709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String mesg = String.format("Test failed!"
4719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " cannot find instance at %s",
4729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        date);
4739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, mesg);
4749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
4759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertTrue(found);
4769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
4779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
4789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
4799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
4819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This class stores all the useful information about an event.
4829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
4839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class EventInfo {
4849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mTitle;
4859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mDescription;
4869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mTimezone;
4879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        boolean mAllDay;
4889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mDtstart;
4899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mDtend;
4909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mRrule;
4919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mDuration;
4929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String mOriginalTitle;
4939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mOriginalInstance;
4949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int mSyncId;
4959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for normal events, using the default timezone
4979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String startDate, String endDate,
4989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay) {
4999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, startDate, endDate, allDay, DEFAULT_TIMEZONE);
5009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for normal events, specifying the timezone
5039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String startDate, String endDate,
5049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay, String timezone) {
5059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, startDate, endDate, allDay, timezone);
5069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String title, String startDate, String endDate,
5099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay, String timezone) {
5109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTitle = title;
5119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time();
5129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = Time.TIMEZONE_UTC;
5149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else if (timezone != null) {
5159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = timezone;
5169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTimezone = time.timezone;
5189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
5199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtstart = time.toMillis(false /* use isDst */);
5209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
5219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtend = time.toMillis(false /* use isDst */);
5229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDuration = null;
5239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mRrule = null;
5249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAllDay = allDay;
5259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for repeating events, using the default timezone
5289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String description, String startDate, String endDate,
5299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay) {
5309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, rrule, allDay, DEFAULT_TIMEZONE);
5319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for repeating events, specifying the timezone
5349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String title, String description, String startDate, String endDate,
5359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay, String timezone) {
5369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, rrule, allDay, timezone);
5379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String title, String description, String startDate, String endDate,
5409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule, boolean allDay, String timezone) {
5419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTitle = title;
5429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDescription = description;
5439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time();
5449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = Time.TIMEZONE_UTC;
5469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else if (timezone != null) {
5479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.timezone = timezone;
5489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mTimezone = time.timezone;
5509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
5519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mDtstart = time.toMillis(false /* use isDst */);
5529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (endDate != null) {
5539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                time.parse3339(endDate);
5549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDtend = time.toMillis(false /* use isDst */);
5559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (allDay) {
5579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long days = 1;
5589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (endDate != null) {
5599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    days = (mDtend - mDtstart) / DateUtils.DAY_IN_MILLIS;
5609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
5619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDuration = "P" + days + "D";
5629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else {
5639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long seconds = (mDtend - mDtstart) / DateUtils.SECOND_IN_MILLIS;
5649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                mDuration = "P" + seconds + "S";
5659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
5669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mRrule = rrule;
5679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAllDay = allDay;
5689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Constructor for recurrence exceptions, using the default timezone
5719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public EventInfo(String originalTitle, String originalInstance, String title,
5729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String description, String startDate, String endDate, boolean allDay) {
5739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(originalTitle, originalInstance,
5749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    title, description, startDate, endDate, allDay, DEFAULT_TIMEZONE);
5759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public void init(String originalTitle, String originalInstance,
5789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String title, String description, String startDate, String endDate,
5799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay, String timezone) {
5809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mOriginalTitle = originalTitle;
5819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(timezone);
5829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(originalInstance);
5839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mOriginalInstance = time.toMillis(false /* use isDst */);
5849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            init(title, description, startDate, endDate, null /* rrule */, allDay, timezone);
5859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
5869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
5879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private class InstanceInfo {
5899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        EventInfo mEvent;
5909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mBegin;
5919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long mEnd;
5929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int mExpectedOccurrences;
5939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public InstanceInfo(String eventName, String startDate, String endDate, int expected) {
5959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Find the test index that contains the given event name
5969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mEvent = findEvent(eventName);
5979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Time time = new Time(mEvent.mTimezone);
5989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(startDate);
5999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mBegin = time.toMillis(false /* use isDst */);
6009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            time.parse3339(endDate);
6019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mEnd = time.toMillis(false /* use isDst */);
6029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mExpectedOccurrences = expected;
6039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
6049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
6059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
6079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This is the main table of events.  The events in this table are
6089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * referred to by name in other places.
6099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
6109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private EventInfo[] mEvents = {
6119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", false),
6129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal1", "2008-05-26T08:30:00", "2008-05-26T09:30:00", false),
6139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("normal2", "2008-05-26T14:30:00", "2008-05-26T15:30:00", false),
6149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday0", "2008-05-02T00:00:00", "2008-05-03T00:00:00", true),
6159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday1", "2008-05-02T00:00:00", "2008-05-31T00:00:00", true),
6169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "daily from 5/1/2008 12am to 1am",
6179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T00:00:00", "2008-05-01T01:00:00",
6189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;WKST=SU", false),
6199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily1", "daily from 5/1/2008 8:30am to 9:30am until 5/3/2008 8am",
6209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T08:30:00", "2008-05-01T09:30:00",
6219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T150000Z;WKST=SU", false),
6229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily2", "daily from 5/1/2008 8:45am to 9:15am until 5/3/2008 10am",
6239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T08:45:00", "2008-05-01T09:15:00",
6249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T170000Z;WKST=SU", false),
6259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday daily0", "all-day daily from 5/1/2008",
6269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;WKST=SU", true),
6289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday daily1", "all-day daily from 5/1/2008 until 5/3/2008",
6299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=DAILY;UNTIL=20080503T000000Z;WKST=SU", true),
6319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday weekly0", "all-day weekly from 5/1/2008",
6329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", null,
6339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;WKST=SU", true),
6349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday weekly1", "all-day for 2 days weekly from 5/1/2008",
6359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01", "2008-05-03",
6369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;WKST=SU", true),
6379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("allday yearly0", "all-day yearly on 5/1/2008",
6389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T", null,
6399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=YEARLY;WKST=SU", true),
6409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "weekly from 5/6/2008 on Tue 1pm to 2pm",
6419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-06T13:00:00", "2008-05-06T14:00:00",
6429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;BYDAY=TU;WKST=MO", false),
6439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly1", "every 2 weeks from 5/6/2008 on Tue from 2:30pm to 3:30pm",
6449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-06T14:30:00", "2008-05-06T15:30:00",
6459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=WEEKLY;INTERVAL=2;BYDAY=TU;WKST=MO", false),
6469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly0", "monthly from 5/20/2008 on the 3rd Tues from 3pm to 4pm",
6479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-20T15:00:00", "2008-05-20T16:00:00",
6489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;BYDAY=3TU;WKST=SU", false),
6499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly1", "monthly from 5/1/2008 on the 1st from 12:00am to 12:10am",
6509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T00:00:00", "2008-05-01T00:10:00",
6519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=1", false),
6529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("monthly2", "monthly from 5/31/2008 on the 31st 11pm to midnight",
6539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-31T23:00:00", "2008-06-01T00:00:00",
6549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=31", false),
6559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-01T00:00:00",
6569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except0", "daily0 exception for 5/1/2008 12am, change to 5/1/2008 2am to 3am",
6579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T02:00:00", "2008-05-01T01:03:00", false),
6589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-03T00:00:00",
6599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except1", "daily0 exception for 5/3/2008 12am, change to 5/3/2008 2am to 3am",
6609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-03T02:00:00", "2008-05-03T01:03:00", false),
6619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("daily0", "2008-05-02T00:00:00",
6629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except2", "daily0 exception for 5/2/2008 12am, change to 1/2/2008",
6639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-01-02T00:00:00", "2008-01-02T01:00:00", false),
6649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "2008-05-13T13:00:00",
6659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "except3", "daily0 exception for 5/11/2008 1pm, change to 12/11/2008 1pm",
6669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-12-11T13:00:00", "2008-12-11T14:00:00", false),
6679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("weekly0", "2008-05-13T13:00:00",
6689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "cancel0", "weekly0 exception for 5/13/2008 1pm",
6699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-13T13:00:00", "2008-05-13T14:00:00", false),
6709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new EventInfo("yearly0", "yearly on 5/1/2008 from 1pm to 2pm",
6719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "2008-05-01T13:00:00", "2008-05-01T14:00:00",
6729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    "FREQ=YEARLY;WKST=SU", false),
6739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
6749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
676bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * This table is used to verify the events generated by mEvents.  It checks that the
6779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * number of instances within a given range matches the expected number
6789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * of instances.
6799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
6809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private InstanceInfo[] mInstanceRanges = {
6819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-01T00:01:00", 1),
6829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-01T01:00:00", 1),
6839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 2),
6849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-02T23:59:00", 2),
6859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-02T00:01:00", 1),
6869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-02T01:00:00", 1),
6879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-02T00:00:00", "2008-05-03T00:00:00", 2),
6889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 31),
6899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily0", "2008-05-01T00:00:00", "2008-06-01T23:59:00", 32),
6909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily1", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 1),
6929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily1", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 2),
6939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily2", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 1),
6959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("daily2", "2008-05-01T00:00:00", "2008-05-31T23:59:00", 3),
6969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
6979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday daily0", "2008-05-01", "2008-05-07", 7),
6989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday daily1", "2008-05-01", "2008-05-07", 3),
6999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-07", 1),
7009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-08", 2),
7019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly0", "2008-05-01", "2008-05-31", 5),
7029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday weekly1", "2008-05-01", "2008-05-31", 5),
7039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday yearly0", "2008-05-01", "2009-04-30", 1),
7049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("allday yearly0", "2008-05-01", "2009-05-02", 2),
7059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 0),
7079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-06T00:00:00", "2008-05-07T00:00:00", 1),
7089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 4),
7099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly0", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 8),
7109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-05-02T00:00:00", 0),
7129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-06T00:00:00", "2008-05-07T00:00:00", 1),
7139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 2),
7149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("weekly1", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 4),
7159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-20T13:00:00", 0),
7179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-20T15:00:00", 1),
7189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-05-31T00:00:00", 0),
7199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-06-17T14:59:00", 0),
7209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-20T16:01:00", "2008-06-17T15:00:00", 1),
7219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 1),
7229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly0", "2008-05-01T00:00:00", "2008-06-30T00:00:00", 2),
7239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-05-01T01:00:00", 1),
7259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 1),
7269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:10:00", "2008-05-31T23:59:00", 1),
7279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:11:00", "2008-05-31T23:59:00", 0),
7289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly1", "2008-05-01T00:00:00", "2008-06-01T00:00:00", 2),
7299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-05-31T00:00:00", 0),
7319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:10:00", "2008-05-31T23:00:00", 1),
7329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-07-01T00:00:00", 1),
7339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("monthly2", "2008-05-01T00:00:00", "2008-08-01T00:00:00", 2),
7349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("yearly0", "2008-05-01", "2009-04-30", 1),
7369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new InstanceInfo("yearly0", "2008-05-01", "2009-05-02", 2),
7379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some events.
7419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mNormalInsertDelete = {
7439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal0"),
7449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal1"),
7459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("normal2"),
7469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-31T00:01:00", 3),
7470739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
7499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-31T00:01:00", 2),
7500739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal1", 0, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7510739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal2", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
7530739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("normal0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
7559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some all-day events.
7599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mAlldayInsertDelete = {
7619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("allday0"),
7629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("allday1"),
7639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
7649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-01T00:01:00", 0),
7659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-02T00:00:00", "2008-05-02T00:01:00", 2),
7669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-03T00:00:00", "2008-05-03T00:01:00", 1),
7670739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("allday0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
7699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-02T00:00:00", "2008-05-02T00:01:00", 1),
7709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-03T00:00:00", "2008-05-03T00:01:00", 1),
7710739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("allday1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
7739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands inserts and deletes some repeating events.
7779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mRecurringInsertDelete = {
7799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
7809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily1"),
7819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
7829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-02T00:01:00", 3),
7839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T01:01:00", "2008-05-02T00:01:00", 2),
7849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00", 6),
7850739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("daily1", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
7879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-02T00:01:00", 2),
7889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00", 4),
7890739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            new Delete("daily0", 1, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
7909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(0),
7919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
7929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
7939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
7949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
7959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception that moves an event outside the expansion window.  It checks that the
7969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * recurrence exception does not occur in the Instances database table.
7979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Bug 1642665
7989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
7999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithMovedRecurrence = {
8009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
8019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
8029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-03T00:00:00", }),
8049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except2"),
8059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
8069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-03T00:00:00"}),
8079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands deletes (cancels) one instance of a recurrence.
8119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mCancelInstance = {
8139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("weekly0"),
8149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-22T00:01:00",
8159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-06T13:00:00", "2008-05-13T13:00:00",
8169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-20T13:00:00", }),
8179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("cancel0"),
8189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("cancel0", new KeyValue[] {
819b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    new KeyValue(CalendarContract.Events.STATUS,
820b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        Integer.toString(CalendarContract.Events.STATUS_CANCELED)),
8219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
8229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-22T00:01:00",
8239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-06T13:00:00",
8249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-05-20T13:00:00", }),
8259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
8289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception that moves an event from outside the expansion window into the
8299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * expansion window.
8309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithMovedRecurrence2 = {
8329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("weekly0"),
8339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-12-01T00:00:00", "2008-12-22T00:01:00",
8349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-12-02T13:00:00", "2008-12-09T13:00:00",
8359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-12-16T13:00:00", }),
8369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except3"),
8379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-12-01T00:00:00", "2008-12-22T00:01:00",
8389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-12-02T13:00:00", "2008-12-09T13:00:00",
8399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                            "2008-12-11T13:00:00", "2008-12-16T13:00:00", }),
8409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This sequence of commands creates a recurring event with a recurrence
8439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * exception and then changes the end time of the recurring event.  It then
8449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * checks that the recurrence exception does not occur in the Instances
8459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * database table.
8469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[]
8489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mExceptionWithTruncatedRecurrence = {
8499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("daily0"),
8509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify 4 occurrences of the "daily0" repeating event
8519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8537e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T00:00:00", "2008-05-04T00:00:00"}),
8549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Insert("except1"),
8559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(2),
8569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that one of the 4 occurrences has its start time changed
8589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // so that it now matches the recurrence exception.
8599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T02:00:00", "2008-05-04T00:00:00"}),
8629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Change the end time of "daily0" but it still includes the
8649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // recurrence exception.
8659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("daily0", new KeyValue[] {
8669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new KeyValue(Events.RRULE, "FREQ=DAILY;UNTIL=20080505T150000Z;WKST=SU"),
8679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
8689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that the recurrence exception is still there
8709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00",
8727e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                            "2008-05-03T02:00:00", "2008-05-04T00:00:00"}),
8739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This time change the end time of "daily0" so that it excludes
8749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // the recurrence exception.
8759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("daily0", new KeyValue[] {
8769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new KeyValue(Events.RRULE, "FREQ=DAILY;UNTIL=20080502T150000Z;WKST=SU"),
8779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
8789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // The server will cancel the out-of-range exception.
8799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // It would be nice for the provider to handle this automatically,
8809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // but for now simulate the server-side cancel.
8819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new Update("except1", new KeyValue[] {
882b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                new KeyValue(CalendarContract.Events.STATUS,
883b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        Integer.toString(CalendarContract.Events.STATUS_CANCELED)),
8849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }),
8859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Verify that the recurrence exception does not appear.
8869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-04T00:01:00",
8879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T00:00:00", "2008-05-02T00:00:00"}),
8889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
8899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
8909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
8919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Bug 135848.  Ensure that a recurrence exception is displayed even if the recurrence
8929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * is not present.
8939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
8949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Command[] mExceptionWithNoRecurrence = {
8957e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            new Insert("except0"),
8969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new QueryNumEvents(1),
8979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            new VerifyAllInstances("2008-05-01T00:00:00", "2008-05-03T00:01:00",
8989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    new String[] {"2008-05-01T02:00:00"}),
8999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    };
9009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private EventInfo findEvent(String name) {
9029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
9039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
9049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
9059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (name.equals(event.mTitle)) {
9069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                return event;
9079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
9089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
9099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return null;
9109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
9119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
9139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected void setUp() throws Exception {
9149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        super.setUp();
91581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // This code here is the code that was originally in ProviderTestCase2
91681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mResolver = new MockContentResolver();
91781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
91881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String filenamePrefix = "test.";
91981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
92081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                new MockContext2(), // The context that most methods are delegated to
92181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                getContext(), // The context that file methods are delegated to
92281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                filenamePrefix);
92381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mContext = new IsolatedContext(mResolver, targetContextWrapper);
9249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
92581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mProvider = new CalendarProvider2ForTesting();
92681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        mProvider.attachInfo(mContext, null);
92781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
928b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.addProvider(CalendarContract.AUTHORITY, mProvider);
9299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mResolver.addProvider("subscribedfeeds", new MockProvider("subscribedfeeds"));
9309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mResolver.addProvider("sync", new MockProvider("sync"));
9319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
9329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mMetaData = getProvider().mMetaData;
933e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        mForceDtend = false;
934c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
935c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
936c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        mDb = helper.getWritableDatabase();
937c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        wipeAndInitData(helper, mDb);
9389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
9399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
94081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @Override
94181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected void tearDown() throws Exception {
94281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
94381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            mDb.close();
94481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            mDb = null;
94581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            getProvider().getDatabaseHelper().close();
94681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } catch (IllegalStateException e) {
94781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            e.printStackTrace();
94881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
94981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        super.tearDown();
95081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
95126d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff
952c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    public void wipeAndInitData(SQLiteOpenHelper helper, SQLiteDatabase db)
953c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            throws CalendarCache.CacheException {
954c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.beginTransaction();
955c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
956c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Clean tables
957c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Calendars", null, null);
958c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Events", null, null);
959c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("EventsRawTimes", null, null);
960c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Instances", null, null);
961c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarMetaData", null, null);
962c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarCache", null, null);
963c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Attendees", null, null);
964c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("Reminders", null, null);
965c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("CalendarAlerts", null, null);
966c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.delete("ExtendedProperties", null, null);
967c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
968c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Set CalendarCache data
969c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        initCalendarCacheLocked(helper, db);
970c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
971c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // set CalendarMetaData data
972c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long now = System.currentTimeMillis();
973c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        ContentValues values = new ContentValues();
974c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("localTimezone", "America/Los_Angeles");
975c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("minInstance", 1207008000000L); // 1st April 2008
976c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        values.put("maxInstance", now + ONE_WEEK_MILLIS);
977c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.insert("CalendarMetaData", null, values);
978c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
979c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.setTransactionSuccessful();
980c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        db.endTransaction();
981c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    }
982c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
983c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    private void initCalendarCacheLocked(SQLiteOpenHelper helper, SQLiteDatabase db)
984c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            throws CalendarCache.CacheException {
985c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
986c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
987c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String localTimezone = TimeZone.getDefault().getID();
988c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
989c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        // Set initial values
990c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_DATABASE_VERSION, "2010k");
991c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_TYPE, CalendarCache.TIMEZONE_TYPE_AUTO);
992c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_INSTANCES, localTimezone);
993c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        cache.writeDataLocked(db, CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS, localTimezone);
99426d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff    }
99526d0bf3c34f170f9398ac32bf04b87d4957a4441Ken Shirriff
99681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    protected CalendarProvider2ForTesting getProvider() {
99781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        return mProvider;
9989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
9999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
10019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Dumps the contents of the given cursor to the log.  For debugging.
10029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param cursor the database cursor
10039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
10049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void dumpCursor(Cursor cursor) {
10059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToPosition(-1);
10069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String[] cols = cursor.getColumnNames();
10079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "dumpCursor() count: " + cursor.getCount());
10099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int index = 0;
10109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
10119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, index + " {");
10129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            for (int i = 0; i < cols.length; i++) {
10139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.i(TAG, "    " + cols[i] + '=' + cursor.getString(i));
10149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
10159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Log.i(TAG, "}");
10169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            index += 1;
10179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToPosition(-1);
10199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
10209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int insertCal(String name, String timezone) {
10220739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        return insertCal(name, timezone, DEFAULT_ACCOUNT);
1023205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    }
1024205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
1025bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
1026bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Creates a new calendar, with the provided name, time zone, and account name.
1027bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     *
1028bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * @return the new calendar's _ID value
1029bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
1030205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    private int insertCal(String name, String timezone, String account) {
10319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues m = new ContentValues();
10329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Calendars.NAME, name);
103302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        m.put(Calendars.CALENDAR_DISPLAY_NAME, name);
1034c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        m.put(Calendars.CALENDAR_COLOR, "0xff123456");
103502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        m.put(Calendars.CALENDAR_TIME_ZONE, timezone);
10364067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        m.put(Calendars.VISIBLE, 1);
1037fa332ecedc0c340109811552407142f6e4f600b2RoboErik        m.put(Calendars.CAL_SYNC1, CALENDAR_URL);
1038c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        m.put(Calendars.OWNER_ACCOUNT, account);
1039c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        m.put(Calendars.ACCOUNT_NAME,  account);
1040c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        m.put(Calendars.ACCOUNT_TYPE, DEFAULT_ACCOUNT_TYPE);
1041eb7ee6232dc1f62b7bf71abc8e706cbf81b00235Fabrice Di Meglio        m.put(Calendars.SYNC_EVENTS,  1);
10429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10430739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        Uri url = mResolver.insert(
10440739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                addSyncQueryParams(mCalendarsUri, account, DEFAULT_ACCOUNT_TYPE), m);
10459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String id = url.getLastPathSegment();
10469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return Integer.parseInt(id);
10479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
10489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1049bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
1050bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Constructs a URI from a base URI (e.g. "content://com.android.calendar/calendars"),
1051bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * an account name, and an account type.
1052bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
10530739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private Uri addSyncQueryParams(Uri uri, String account, String accountType) {
1054b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        return uri.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
1055c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
1056c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
10570739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    }
10580739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik
105974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private int deleteMatchingCalendars(String selection, String[] selectionArgs) {
106074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        return mResolver.delete(mCalendarsUri, selection, selectionArgs);
106174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
106274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
10639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Uri insertEvent(int calId, EventInfo event) {
10649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (mWipe) {
10659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Wipe instance table so it will be regenerated
10669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mMetaData.clearInstanceRange();
10679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues m = new ContentValues();
10699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.CALENDAR_ID, calId);
10709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.TITLE, event.mTitle);
10719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.DTSTART, event.mDtstart);
10729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        m.put(Events.ALL_DAY, event.mAllDay ? 1 : 0);
10739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1074e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        if (event.mRrule == null || mForceDtend) {
10759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a normal event
10769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DTEND, event.mDtend);
1077e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        }
1078e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        if (event.mRrule != null) {
10799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a repeating event
10809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.RRULE, event.mRrule);
10819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DURATION, event.mDuration);
10829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mDescription != null) {
10859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.DESCRIPTION, event.mDescription);
10869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mTimezone != null) {
10889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.EVENT_TIMEZONE, event.mTimezone);
10899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
10909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
10919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (event.mOriginalTitle != null) {
10929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // This is a recurrence exception.
10939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo recur = findEvent(event.mOriginalTitle);
10949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertNotNull(recur);
10959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            String syncId = String.format("%d", recur.mSyncId);
1096c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            m.put(Events.ORIGINAL_SYNC_ID, syncId);
10979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.ORIGINAL_ALL_DAY, recur.mAllDay ? 1 : 0);
10989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            m.put(Events.ORIGINAL_INSTANCE_TIME, event.mOriginalInstance);
10999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
11009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = mResolver.insert(mEventsUri, m);
11019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Create a fake _sync_id and add it to the event.  Update the database
11039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // directly so that we don't trigger any validation checks in the
11049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // CalendarProvider.
11059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long id = ContentUris.parseId(url);
11069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mDb.execSQL("UPDATE Events SET _sync_id=" + mGlobalSyncId + " WHERE _id=" + id);
11079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        event.mSyncId = mGlobalSyncId;
11089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mGlobalSyncId += 1;
11099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return url;
11119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
11129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
11149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Deletes all the events that match the given title.
11159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param title the given title to match events on
11169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @return the number of rows deleted
11179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
11180739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private int deleteMatchingEvents(String title, String account, String accountType) {
11199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor = mResolver.query(mEventsUri, new String[] { Events._ID },
11209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "title=?", new String[] { title }, null);
11219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numRows = 0;
11229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
11239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            long id = cursor.getLong(0);
1124205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // Do delete as a sync adapter so event is really deleted, not just marked
1125205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // as deleted.
11260739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            Uri uri = updatedUri(ContentUris.withAppendedId(Events.CONTENT_URI, id), true, account,
11270739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                    accountType);
11289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numRows += mResolver.delete(uri, null, null);
11299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
11309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
11319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return numRows;
11329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
11339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
11359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Updates all the events that match the given title.
11369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param title the given title to match events on
11379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @return the number of rows updated
11389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
11399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private int updateMatchingEvents(String title, ContentValues values) {
11409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String[] projection = new String[] {
11419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events._ID,
11429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DTSTART,
11439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DTEND,
11449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.DURATION,
11459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.ALL_DAY,
11469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.RRULE,
11479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Events.EVENT_TIMEZONE,
1148c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                Events.ORIGINAL_SYNC_ID,
11499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        };
11509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor = mResolver.query(mEventsUri, projection,
11519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "title=?", new String[] { title }, null);
11529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numRows = 0;
11539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        while (cursor.moveToNext()) {
11549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            long id = cursor.getLong(0);
11559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // If any of the following fields are being changed, then we need
11579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // to include all of them.
11589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (values.containsKey(Events.DTSTART) || values.containsKey(Events.DTEND)
11599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.DURATION) || values.containsKey(Events.ALL_DAY)
11609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.RRULE)
11619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    || values.containsKey(Events.EVENT_TIMEZONE)
1162b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    || values.containsKey(CalendarContract.Events.STATUS)) {
11639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long dtstart = cursor.getLong(1);
11649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                long dtend = cursor.getLong(2);
11659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String duration = cursor.getString(3);
11669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                boolean allDay = cursor.getInt(4) != 0;
11679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String rrule = cursor.getString(5);
11689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String timezone = cursor.getString(6);
11699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String originalEvent = cursor.getString(7);
11709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DTSTART)) {
11729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DTSTART, dtstart);
11739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                // Don't add DTEND for repeating events
11759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DTEND) && rrule == null) {
11769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DTEND, dtend);
11779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.DURATION) && duration != null) {
11799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.DURATION, duration);
11809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.ALL_DAY)) {
11829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.ALL_DAY, allDay ? 1 : 0);
11839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.RRULE) && rrule != null) {
11859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.RRULE, rrule);
11869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (!values.containsKey(Events.EVENT_TIMEZONE) && timezone != null) {
11889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    values.put(Events.EVENT_TIMEZONE, timezone);
11899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
1190c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                if (!values.containsKey(Events.ORIGINAL_SYNC_ID) && originalEvent != null) {
1191c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                    values.put(Events.ORIGINAL_SYNC_ID, originalEvent);
11929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
11939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
11949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
11969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numRows += mResolver.update(uri, values, null, null);
11979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
11989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
11999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return numRows;
12009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
12019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1202ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    /**
1203ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * Updates the status of all the events that match the given title.
1204ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * @param title the given title to match events on
1205ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     * @return the number of rows updated
1206ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik     */
1207ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    private int updateMatchingEventsStatusOnly(String title, ContentValues values) {
1208ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        String[] projection = new String[] {
1209ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                Events._ID,
1210ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        };
1211ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        if (values.size() != 1 && !values.containsKey(Events.STATUS)) {
1212ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            return 0;
1213ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        }
1214ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        Cursor cursor = mResolver.query(mEventsUri, projection,
1215ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik                "title=?", new String[] { title }, null);
1216ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        int numRows = 0;
1217ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        while (cursor.moveToNext()) {
1218ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            long id = cursor.getLong(0);
1219ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
1220ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
1221ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik            numRows += mResolver.update(uri, values, null, null);
1222ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        }
1223ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        cursor.close();
1224ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik        return numRows;
1225ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik    }
1226ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
1227ff036559eeca89b5e6ec138bfdc6a16c76f209e9Erik
12289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void deleteAllEvents() {
12299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mDb.execSQL("DELETE FROM Events;");
12309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mMetaData.clearInstanceRange();
12319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
12329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInsertNormalEvents() throws Exception {
12349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
12359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
12369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
12389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
12409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
12419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Keep track of the number of normal events
12449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numEvents = 0;
12459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // "begin" is the earliest start time of all the normal events,
12479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // and "end" is the latest end time of all the normal events.
12489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long begin = 0, end = 0;
12499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
12519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
12529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
12539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Skip repeating events and recurrence exceptions
12549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (event.mRrule != null || event.mOriginalTitle != null) {
12559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                continue;
12569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
12579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (numEvents == 0) {
12589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                begin = event.mDtstart;
12599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                end = event.mDtend;
12609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            } else {
12619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (begin > event.mDtstart) {
12629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    begin = event.mDtstart;
12639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
12649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                if (end < event.mDtend) {
12659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    end = event.mDtend;
12669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
12679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
12689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            url = insertEvent(calId, event);
12699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numEvents += 1;
12709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
12719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query one
12739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(url, null, null, null, null);
12749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(1, cursor.getCount());
12759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query all
12789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
12799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(numEvents, cursor.getCount());
12809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Check that the Instances table has one instance of each of the
12839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // normal events.
12849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = queryInstances(begin, end);
12859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(numEvents, cursor.getCount());
12869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
12889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInsertRepeatingEvents() throws Exception {
12909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
12919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
12929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int calId = insertCal("Calendar0", "America/Los_Angeles");
12949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
12969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
12979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
12989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
12999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Keep track of the number of repeating events
13009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int numEvents = 0;
13019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mEvents.length;
13039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
13049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = mEvents[ii];
13059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            // Skip normal events
13069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (event.mRrule == null) {
13079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                continue;
13089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
13099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            url = insertEvent(calId, event);
13109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            numEvents += 1;
13119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
13129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query one
13149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(url, null, null, null, null);
13159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(1, cursor.getCount());
13169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
13179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // query all
13199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
13209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(numEvents, cursor.getCount());
13219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
13229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
13239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1324e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    // Force a dtend value to be set and make sure instance expansion still works
1325e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    public void testInstanceRangeDtend() throws Exception {
1326e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        mForceDtend = true;
1327e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff        testInstanceRange();
1328e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff    }
1329e604c19770482e181aa60a611b861ce5d8ed67d7Ken Shirriff
13309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testInstanceRange() throws Exception {
13319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
13329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
13339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int calId = insertCal("Calendar0", "America/Los_Angeles");
13359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
13379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
13389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
13399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
13409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int len = mInstanceRanges.length;
13419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (int ii = 0; ii < len; ii++) {
13429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            InstanceInfo instance = mInstanceRanges[ii];
13439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            EventInfo event = instance.mEvent;
13449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            url = insertEvent(calId, event);
13459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor = queryInstances(instance.mBegin, instance.mEnd);
13469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            if (instance.mExpectedOccurrences != cursor.getCount()) {
13479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, "Test failed! Instance index: " + ii);
13489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Log.e(TAG, "title: " + event.mTitle + " desc: " + event.mDescription
13499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " [begin,end]: [" + instance.mBegin + " " + instance.mEnd + "]"
13509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        + " expected: " + instance.mExpectedOccurrences);
13519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                dumpCursor(cursor);
13529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
13539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(instance.mExpectedOccurrences, cursor.getCount());
13549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            cursor.close();
1355205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff            // Delete as sync_adapter so event is really deleted.
13560739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            int rows = mResolver.delete(
13570739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                    updatedUri(url, true, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
1358205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff                    null /* selection */, null /* selection args */);
13599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(1, rows);
13609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
13619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
13629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
136381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public static <T> void assertArrayEquals(T[] expected, T[] actual) {
136481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        if (!Arrays.equals(expected, actual)) {
136581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            fail("expected:<" + Arrays.toString(expected) +
136681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                "> but was:<" + Arrays.toString(actual) + ">");
136781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
136881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
136981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
137081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
1371dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    public void testEscapeSearchToken() {
1372dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String token = "test";
1373dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String expected = "test";
1374dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1375dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1376dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "%";
1377dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#%";
1378dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1379dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1380dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "_";
1381dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#_";
1382dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1383dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1384dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "#";
1385dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "##";
1386dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1387dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1388dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "##";
1389dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "####";
1390dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1391dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1392dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "%_#";
1393dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "#%#_##";
1394dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1395dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1396dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        token = "blah%blah";
1397dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "blah#%blah";
1398dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertEquals(expected, mProvider.escapeSearchToken(token));
1399dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    }
1400dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1401dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang    @SmallTest @Smoke
140281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testTokenizeSearchQuery() {
140381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String query = "";
1404dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String[] expectedTokens = new String[] {};
140581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
140681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
140781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "a";
140881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"a"};
140981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
141081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
1411dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "word";
1412dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"word"};
1413dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1414dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
141581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "two words";
141681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"two", "words"};
141781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
141881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
141981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        query = "test, punctuation.";
142081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expectedTokens = new String[] {"test", "punctuation"};
142181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1422dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1423dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "\"test phrase\"";
1424dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"test phrase"};
1425dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1426dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1427dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "unquoted \"this is quoted\"";
1428dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"unquoted", "this is quoted"};
1429dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1430dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1431dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = " \"this is quoted\"  unquoted ";
1432dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"this is quoted", "unquoted"};
1433dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1434dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1435dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "escap%e m_e";
1436dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"escap#%e", "m#_e"};
1437dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1438dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1439dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "'a bunch' of malformed\" things";
1440dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"a", "bunch", "of", "malformed", "things"};
1441dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
1442dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1443dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        query = "''''''....,.''trim punctuation";
1444dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expectedTokens = new String[] {"trim", "punctuation"};
1445dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        assertArrayEquals(expectedTokens, mProvider.tokenizeSearchQuery(query));
144681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
144781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
144881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
144981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testConstructSearchWhere() {
145081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String[] tokens = new String[] {"red"};
1451dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        String expected = "(title LIKE ? ESCAPE \"#\" OR "
145218f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
145318f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
145418f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
145518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
145681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
145781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
145881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {};
145981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expected = "";
146081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
146181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
146281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red", "green"};
1463dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "(title LIKE ? ESCAPE \"#\" OR "
1464dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "description LIKE ? ESCAPE \"#\" OR "
146518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "eventLocation LIKE ? ESCAPE \"#\" OR "
146618f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
146718f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" ) AND "
1468dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "(title LIKE ? ESCAPE \"#\" OR "
1469dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                + "description LIKE ? ESCAPE \"#\" OR "
147018f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "eventLocation LIKE ? ESCAPE \"#\" OR "
147118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
147218f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
147381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
147481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
147581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red blue", "green"};
1476dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        expected = "(title LIKE ? ESCAPE \"#\" OR "
147718f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
147818f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
147918f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
148018f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" ) AND "
148118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "(title LIKE ? ESCAPE \"#\" OR "
148218f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "description LIKE ? ESCAPE \"#\" OR "
148318f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "eventLocation LIKE ? ESCAPE \"#\" OR "
148418f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeEmail) LIKE ? ESCAPE \"#\" OR "
148518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang            + "group_concat(attendeeName) LIKE ? ESCAPE \"#\" )";
148681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertEquals(expected, mProvider.constructSearchWhere(tokens));
148781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
148881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
148981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    @SmallTest @Smoke
149081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testConstructSearchArgs() {
149181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        long rangeBegin = 0;
149281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        long rangeEnd = 10;
149381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
149481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String[] tokens = new String[] {"red"};
149518f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang        String[] expected = new String[] {"10", "0", "%red%", "%red%",
149618f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%red%", "%red%", "%red%" };
149781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens,
149881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                rangeBegin, rangeEnd));
149981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
150081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {"red", "blue"};
150118f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang        expected = new String[] { "10", "0", "%red%", "%red%", "%red%",
150218f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%red%", "%red%", "%blue%", "%blue%",
150318f75d6fe8dd0b4fb1deb5e56b4356ae6527bdbcMason Tang                "%blue%", "%blue%","%blue%"};
150481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens,
150581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                rangeBegin, rangeEnd));
150681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
150781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        tokens = new String[] {};
150881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        expected = new String[] {"10", "0" };
150981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        assertArrayEquals(expected, mProvider.constructSearchArgs(tokens,
151081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                rangeBegin, rangeEnd));
151181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
151281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
151381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    public void testInstanceSearchQuery() throws Exception {
151481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String[] PROJECTION = new String[] {
151581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.TITLE,                 // 0
151681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_LOCATION,        // 1
151781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.ALL_DAY,               // 2
1518bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden                Instances.CALENDAR_COLOR,        // 3
151981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_TIMEZONE,        // 4
152081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.EVENT_ID,              // 5
152181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.BEGIN,                 // 6
152281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END,                   // 7
152381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances._ID,                   // 8
152481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.START_DAY,             // 9
152581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END_DAY,               // 10
152681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.START_MINUTE,          // 11
152781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.END_MINUTE,            // 12
152881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.HAS_ALARM,             // 13
152981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.RRULE,                 // 14
153081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.RDATE,                 // 15
153181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Instances.SELF_ATTENDEE_STATUS,  // 16
153281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Events.ORGANIZER,                // 17
153381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                Events.GUESTS_CAN_MODIFY,        // 18
153481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        };
153581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
15362ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik        String orderBy = CalendarProvider2.SORT_CALENDAR_VIEW;
153781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        String where = Instances.SELF_ATTENDEE_STATUS + "!=" +
1538b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED;
153981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
154081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
154181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String START = "2008-05-01T00:00:00";
154281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        final String END = "2008-05-01T20:00:00";
154381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
154481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event1 = new EventInfo("search orange",
154581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
154681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
154781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
154881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
154981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event1.mDescription = "this is description1";
155081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
155181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event2 = new EventInfo("search purple",
155281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
155381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
155481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
155581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
155681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event2.mDescription = "lasers, out of nowhere";
155781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
155881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo event3 = new EventInfo("",
155981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                START,
156081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                END,
156181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                false /* allDay */,
156281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                DEFAULT_TIMEZONE);
156381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        event3.mDescription = "kapow";
156481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
156581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        EventInfo[] events = { event1, event2, event3 };
156681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
156781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[0]);
156881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[1]);
156981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        insertEvent(calId, events[2]);
157081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
157181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        Time time = new Time(DEFAULT_TIMEZONE);
157281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        time.parse3339(START);
157381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        long startMs = time.toMillis(true /* ignoreDst */);
157481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // Query starting from way in the past to one hour into the event.
157581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        // Query is more than 2 months so the range won't get extended by the provider.
157681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        Cursor cursor = null;
157781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
157881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
157981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
158081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
158181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
15822ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "search", where, null, orderBy);
158381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(2, cursor.getCount());
158481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
158581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
158681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
158781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
158881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
158981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
159081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
159181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
159281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
159381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
15942ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "purple", where, null, orderBy);
159581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(1, cursor.getCount());
159681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
159781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
159881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
159981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
160081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
160181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
160281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
160381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
160481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
160581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16062ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "puurple", where, null, orderBy);
160781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(0, cursor.getCount());
160881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
160981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
161081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
161181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
161281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
161381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
161481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
161581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
161681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
161781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16182ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "purple lasers", where, null, orderBy);
161981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(1, cursor.getCount());
162081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
162181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
162281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
162381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
162481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
162581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
162681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        try {
162781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
162881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
162981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16302ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "lasers kapow", where, null, orderBy);
163181d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            assertEquals(0, cursor.getCount());
163281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        } finally {
163381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            if (cursor != null) {
163481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang                cursor.close();
163581d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang            }
1636dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1637dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1638dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
1639dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
1640dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1641dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16422ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "\"search purple\"", where, null, orderBy);
1643dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(1, cursor.getCount());
1644dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1645dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1646dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1647dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
1648dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1649dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1650dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
1651dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
1652dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1653dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16542ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "\"purple search\"", where, null, orderBy);
1655dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(0, cursor.getCount());
1656dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1657dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1658dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1659dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
1660dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        }
1661dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang
1662dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        try {
1663dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            cursor = Instances.query(mResolver, PROJECTION,
1664dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs - DateUtils.YEAR_IN_MILLIS,
1665dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                    startMs + DateUtils.HOUR_IN_MILLIS,
16662ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                    "%", where, null, orderBy);
1667dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            assertEquals(0, cursor.getCount());
1668dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang        } finally {
1669dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            if (cursor != null) {
1670dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang                cursor.close();
1671dc866a1a66871a55810cbf98169f3212fb47acd3Mason Tang            }
167281d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        }
167381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    }
167481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
16759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testEntityQuery() throws Exception {
16769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        testInsertNormalEvents(); // To initialize
16779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues reminder = new ContentValues();
1679b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.EVENT_ID, 1);
1680b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.MINUTES, 10);
1681b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_SMS);
1682b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.Reminders.CONTENT_URI, reminder);
1683b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.MINUTES, 20);
1684b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.Reminders.CONTENT_URI, reminder);
16859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues extended = new ContentValues();
1687b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.NAME, "foo");
1688b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "bar");
1689b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.EVENT_ID, 2);
1690b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.ExtendedProperties.CONTENT_URI, extended);
1691b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.EVENT_ID, 1);
1692b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.ExtendedProperties.CONTENT_URI, extended);
1693b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.NAME, "foo2");
1694b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "bar2");
1695b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.ExtendedProperties.CONTENT_URI, extended);
16969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
16979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues attendee = new ContentValues();
1698b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
1699b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
1700b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_STATUS,
1701b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED);
1702b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
1703b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.TYPE_REQUIRED);
1704b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
1705b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.RELATIONSHIP_PERFORMER);
1706b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, 3);
1707b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
17089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
170919fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana        EntityIterator ei = EventsEntity.newEntityIterator(
171019fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana                mResolver.query(EventsEntity.CONTENT_URI, null, null, null, null), mResolver);
17119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        int count = 0;
17129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        try {
17139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (ei.hasNext()) {
17149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Entity entity = ei.next();
17159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ContentValues values = entity.getEntityValues();
1716fa332ecedc0c340109811552407142f6e4f600b2RoboErik                assertEquals(CALENDAR_URL, values.getAsString(Calendars.CAL_SYNC1));
17179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ArrayList<Entity.NamedContentValues> subvalues = entity.getSubValues();
17189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                switch (values.getAsInteger("_id")) {
17199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    case 1:
17208ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        assertEquals(5, subvalues.size()); // 2 x reminder, 3 x extended properties
17219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
17229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    case 2:
17238ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        // Extended properties (contains originalTimezone)
17248ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        assertEquals(2, subvalues.size());
17258ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        ContentValues subContentValues = subvalues.get(1).values;
1726767a744d42f8e271712d65b2877384355b1398a9Ken Shirriff                        String name = subContentValues.getAsString(
1727b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                                CalendarContract.ExtendedProperties.NAME);
1728767a744d42f8e271712d65b2877384355b1398a9Ken Shirriff                        String value = subContentValues.getAsString(
1729b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                                CalendarContract.ExtendedProperties.VALUE);
1730767a744d42f8e271712d65b2877384355b1398a9Ken Shirriff                        assertEquals("foo", name);
1731767a744d42f8e271712d65b2877384355b1398a9Ken Shirriff                        assertEquals("bar", value);
17329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
17339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    case 3:
17348ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        assertEquals(2, subvalues.size()); // Attendees
17359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
17369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                    default:
17378ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                        assertEquals(1, subvalues.size());
17389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                        break;
17399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                }
17409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                count += 1;
17419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
17429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(5, count);
17439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        } finally {
17449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            ei.close();
17459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
17469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
174719fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana        ei = EventsEntity.newEntityIterator(
174819fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana                    mResolver.query(EventsEntity.CONTENT_URI, null, "_id = 3", null, null),
174919fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana                mResolver);
17509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        try {
17519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            count = 0;
17529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            while (ei.hasNext()) {
17539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                Entity entity = ei.next();
17549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                count += 1;
17559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            }
17569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            assertEquals(1, count);
17579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        } finally {
175819fb3af2ec12621bca575f5518c2ba3831cb3600Fred Quintana            ei.close();
17599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
17609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
17619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
176230c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff    public void testDeleteCalendar() throws Exception {
176330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        int calendarId0 = insertCal("Calendar0", DEFAULT_TIMEZONE);
176430c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        int calendarId1 = insertCal("Calendar1", DEFAULT_TIMEZONE, "user2@google.com");
176530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        insertEvent(calendarId0, mEvents[0]);
176630c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        insertEvent(calendarId1, mEvents[1]);
176730c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 2 calendars and 2 events
1768b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 2);
1769b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 2);
177030c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1771b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int deletes = mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
177230c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                "ownerAccount='user2@google.com'", null /* selectionArgs */);
177330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
177430c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(1, deletes);
177530c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 1 calendar and 1 event
1776b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 1);
1777b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 1);
177830c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1779b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        deletes = mResolver.delete(Uri.withAppendedPath(CalendarContract.Calendars.CONTENT_URI,
178030c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                String.valueOf(calendarId0)),
178130c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                null /* selection*/ , null /* selectionArgs */);
178230c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
178330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(1, deletes);
178430c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        // Should have 0 calendars and 0 events
1785b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 0);
1786b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 0);
178730c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1788b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        deletes = mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
178930c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff                "ownerAccount=?", new String[] {"user2@google.com"} /* selectionArgs */);
179030c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
179130c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff        assertEquals(0, deletes);
179230c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff    }
179330c0d7ae9d4c410254dc4106fa4ffa692a7e6706Ken Shirriff
1794e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff    public void testCalendarAlerts() throws Exception {
1795e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // This projection is from AlertActivity; want to make sure it works.
1796e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        String[] projection = new String[] {
1797b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts._ID,              // 0
1798b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.TITLE,            // 1
1799b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_LOCATION,   // 2
1800b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALL_DAY,          // 3
1801b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.BEGIN,            // 4
1802b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.END,              // 5
1803b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID,         // 6
1804b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.CALENDAR_COLOR,   // 7
1805b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.RRULE,            // 8
1806b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.HAS_ALARM,        // 9
1807b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.STATE,            // 10
1808b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALARM_TIME,       // 11
1809e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        };
1810e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        testInsertNormalEvents(); // To initialize
1811e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1812b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri alertUri = CalendarContract.CalendarAlerts.insert(mResolver, 1 /* eventId */,
1813e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                2 /* begin */, 3 /* end */, 4 /* alarmTime */, 5 /* minutes */);
1814b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        CalendarContract.CalendarAlerts.insert(mResolver, 1 /* eventId */,
1815e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                2 /* begin */, 7 /* end */, 8 /* alarmTime */, 9 /* minutes */);
1816e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1817e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Regular query
1818b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI, projection,
1819e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                null /* selection */, null /* selectionArgs */, null /* sortOrder */);
1820e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1821e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(2, cursor.getCount());
1822e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
1823e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1824e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Instance query
1825e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor = mResolver.query(alertUri, projection,
1826e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff                null /* selection */, null /* selectionArgs */, null /* sortOrder */);
1827e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1828e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(1, cursor.getCount());
1829e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
1830e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1831e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        // Grouped by event query
1832b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        cursor = mResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI_BY_INSTANCE,
1833b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                projection, null /* selection */, null /* selectionArgs */, null /* sortOrder */);
1834e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1835e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        assertEquals(1, cursor.getCount());
1836e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff        cursor.close();
1837e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff    }
1838e74157e34e174c923032a4b93ad298d0f234879cKen Shirriff
1839c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    void checkEvents(int count, SQLiteDatabase db) {
1840c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Cursor cursor = db.query("Events", null, null, null, null, null, null);
1841c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        try {
1842c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            assertEquals(count, cursor.getCount());
1843c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        } finally {
1844c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio            cursor.close();
1845c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        }
1846c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio    }
1847175d0cd257853813cb258c7406af3bf481a36c10Erik
1848175d0cd257853813cb258c7406af3bf481a36c10Erik    void checkEvents(int count, SQLiteDatabase db, String calendar) {
1849175d0cd257853813cb258c7406af3bf481a36c10Erik        Cursor cursor = db.query("Events", null, Events.CALENDAR_ID + "=?", new String[] {calendar},
1850175d0cd257853813cb258c7406af3bf481a36c10Erik                null, null, null);
1851175d0cd257853813cb258c7406af3bf481a36c10Erik        try {
1852175d0cd257853813cb258c7406af3bf481a36c10Erik            assertEquals(count, cursor.getCount());
1853175d0cd257853813cb258c7406af3bf481a36c10Erik        } finally {
1854175d0cd257853813cb258c7406af3bf481a36c10Erik            cursor.close();
1855175d0cd257853813cb258c7406af3bf481a36c10Erik        }
1856175d0cd257853813cb258c7406af3bf481a36c10Erik    }
18579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
18589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Test attendee processing
18599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
18609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
18619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testAttendees() throws Exception {
1862175d0cd257853813cb258c7406af3bf481a36c10Erik        mCalendarId = insertCal("CalendarTestAttendees", DEFAULT_TIMEZONE);
1863175d0cd257853813cb258c7406af3bf481a36c10Erik        String calendarIdString = Integer.toString(mCalendarId);
1864175d0cd257853813cb258c7406af3bf481a36c10Erik        checkEvents(0, mDb, calendarIdString);
18659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri eventUri = insertEvent(mCalendarId, findEvent("daily0"));
18660739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        // TODO This has a race condition that causes checkEvents to not find
18670739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        // the just added event
18680739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        Thread.sleep(200);
1869175d0cd257853813cb258c7406af3bf481a36c10Erik        checkEvents(1, mDb, calendarIdString);
18709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long eventId = ContentUris.parseId(eventUri);
18719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
18729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        ContentValues attendee = new ContentValues();
1873b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
1874b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
1875b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
1876b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.TYPE_REQUIRED);
1877b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
1878b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.RELATIONSHIP_ORGANIZER);
1879b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, eventId);
1880b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri attendeesUri = mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
1881b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik
1882b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver.query(CalendarContract.Attendees.CONTENT_URI, null,
18839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "event_id=" + eventId, null, null);
18840739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("Created event is missing - cannot find EventUri = " + eventUri, 1,
18850739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                cursor.getCount());
18869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
18879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
18889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
1889ab472739446ef9e4a6fdcf9903d6260741d96acfErik Pasternak        // TODO figure out why this test fails. App works fine for this case.
18900739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("Created event is missing - cannot find EventUri = " + eventUri, 1,
18910739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                cursor.getCount());
1892b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int selfColumn = cursor.getColumnIndex(CalendarContract.Events.SELF_ATTENDEE_STATUS);
18939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
18949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        long selfAttendeeStatus = cursor.getInt(selfColumn);
1895b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED, selfAttendeeStatus);
18969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
18979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
18989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Change status to declined
1899b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_STATUS,
1900b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED);
19019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mResolver.update(attendeesUri, attendee, null, null);
19029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
19039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
19049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
19059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        selfAttendeeStatus = cursor.getInt(selfColumn);
1906b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED, selfAttendeeStatus);
19079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
19089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
19099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Add another attendee
1910b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Dude");
1911b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, "dude@dude.com");
1912b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_STATUS,
1913b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED);
1914b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        mResolver.insert(CalendarContract.Attendees.CONTENT_URI, attendee);
19159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
1916b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        cursor = mResolver.query(CalendarContract.Attendees.CONTENT_URI, null,
19179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "event_id=" + mCalendarId, null, null);
19189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(2, cursor.getCount());
19199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
19209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
19219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(eventUri, null, null, null, null);
19229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.moveToNext();
19239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        selfAttendeeStatus = cursor.getInt(selfColumn);
1924b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED, selfAttendeeStatus);
19259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
19269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
19279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
19289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
192934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik     * Test the event's dirty status and clear it.
1930b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik     *
19317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param eventId event to fetch.
193234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik     * @param wanted the wanted dirty status
19337e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
19347e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void testAndClearDirty(long eventId, int wanted) {
19357e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Cursor cursor = mResolver.query(
1936b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId),
19377e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null, null, null, null);
19387e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        try {
19397e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("Event count", 1, cursor.getCount());
19407e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.moveToNext();
1941b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            int dirty = cursor.getInt(cursor.getColumnIndex(CalendarContract.Events.DIRTY));
19427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("dirty flag", wanted, dirty);
19437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            if (dirty == 1) {
19447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                // Have to access database directly since provider will set dirty again.
194534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                mDb.execSQL("UPDATE Events SET " + Events.DIRTY + "=0 WHERE _id=" + eventId);
19467e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            }
19477e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } finally {
19487e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.close();
19497e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
19507e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
19517e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
19527e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
19537e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test the count of results from a query.
19547e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param uri The URI to query
19557e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param where The where string or null.
19567e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param wanted The number of results wanted.  An assertion is thrown if it doesn't match.
19577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
19587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void testQueryCount(Uri uri, String where, int wanted) {
19597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Cursor cursor = mResolver.query(uri, null/* projection */, where, null /* selectionArgs */,
19607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* sortOrder */);
19617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        try {
19627e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            assertEquals("query results", wanted, cursor.getCount());
19637e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } finally {
19647e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            cursor.close();
19657e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
19667e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
19677e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
19687e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
19697e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing.
19707e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
19717e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
19727e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testDirty() throws Exception {
19737e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        internalTestDirty(false);
19747e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
19757e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
19767e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
19777e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing for updates from a sync adapter.
19787e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
19797e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
19807e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testDirtyWithSyncAdapter() throws Exception {
19817e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        internalTestDirty(true);
19827e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
19837e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
19847e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
1985bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Adds CALLER_IS_SYNCADAPTER to URI if this is a sync adapter operation.  Otherwise,
1986bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * returns the original URI.
19877e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
19880739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik    private Uri updatedUri(Uri uri, boolean syncAdapter, String account, String accountType) {
19897e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        if (syncAdapter) {
19900739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik            return addSyncQueryParams(uri, account, accountType);
19917e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        } else {
19927e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            return uri;
19937e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
19947e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
19957e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
19967e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
19977e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test dirty flag processing either for syncAdapter operations or client operations.
19987e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * The main difference is syncAdapter operations don't set the dirty bit.
19997e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
20007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private void internalTestDirty(boolean syncAdapter) throws Exception {
20017e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
20027e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2003c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long now = System.currentTimeMillis();
2004c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long begin = (now / 1000) * 1000;
2005c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long end = begin + ONE_HOUR_MILLIS;
2006c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Time time = new Time(DEFAULT_TIMEZONE);
2007c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        time.set(begin);
2008c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String startDate = time.format3339(false);
2009c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        time.set(end);
2010c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        String endDate = time.format3339(false);
2011c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
2012c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        EventInfo eventInfo = new EventInfo("current", startDate, endDate, false);
2013c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        Uri eventUri = insertEvent(mCalendarId, eventInfo);
20147e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20157e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId = ContentUris.parseId(eventUri);
20167e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 1);
20177e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20187e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues attendee = new ContentValues();
2019b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Joe");
2020b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_EMAIL, DEFAULT_ACCOUNT);
2021b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_TYPE,
2022b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.TYPE_REQUIRED);
2023b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
2024b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.RELATIONSHIP_ORGANIZER);
2025b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, eventId);
20267e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20277e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri attendeeUri = mResolver.insert(
2028b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Attendees.CONTENT_URI, syncAdapter, DEFAULT_ACCOUNT,
20290739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE),
20307e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                attendee);
20317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2032b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 1);
20337e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20347e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues reminder = new ContentValues();
2035b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.MINUTES, 30);
2036b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_EMAIL);
2037b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        reminder.put(CalendarContract.Attendees.EVENT_ID, eventId);
20387e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20397e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri reminderUri = mResolver.insert(
2040b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Reminders.CONTENT_URI, syncAdapter, DEFAULT_ACCOUNT,
20410739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE), reminder);
20427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2043b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Reminders.CONTENT_URI, "event_id=" + eventId, 1);
20447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2045c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio        long alarmTime = begin + 5 * ONE_MINUTE_MILLIS;
2046c3fb804639a62353b76ea45fded1022650c2a73aFabrice Di Meglio
20477e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues alert = new ContentValues();
2048b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.BEGIN, begin);
2049b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.END, end);
2050b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.ALARM_TIME, alarmTime);
2051b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.CREATION_TIME, now);
2052b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.RECEIVED_TIME, now);
2053b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.NOTIFY_TIME, now);
2054b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.STATE, CalendarContract.CalendarAlerts.SCHEDULED);
2055b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.MINUTES, 30);
2056b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.EVENT_ID, eventId);
20577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri alertUri = mResolver.insert(
2059b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.CalendarAlerts.CONTENT_URI, syncAdapter,
2060b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), alert);
20617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
20627e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2063b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 1);
20647e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20657e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        ContentValues extended = new ContentValues();
2066b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.NAME, "foo");
2067b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "bar");
2068b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.EVENT_ID, eventId);
20697e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20707e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri extendedUri = mResolver.insert(
2071b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.ExtendedProperties.CONTENT_URI, syncAdapter,
2072b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), extended);
20737e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2074b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI, "event_id=" + eventId, 2);
20757e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20767e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Now test updates
20777e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20787e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        attendee = new ContentValues();
2079b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.ATTENDEE_NAME, "Sam");
20807e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Need to include EVENT_ID with attendee update.  Is that desired?
2081b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        attendee.put(CalendarContract.Attendees.EVENT_ID, eventId);
20827e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20830739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("update", 1, mResolver.update(
20840739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(attendeeUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
20850739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                attendee,
20867e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
20877e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
20887e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2089b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 1);
20907e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20917e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        alert = new ContentValues();
2092b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        alert.put(CalendarContract.CalendarAlerts.STATE, CalendarContract.CalendarAlerts.DISMISSED);
20937e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
20940739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("update", 1, mResolver.update(
20950739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(alertUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE), alert,
20967e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
20977e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
20987e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2099b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 1);
21007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21017e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        extended = new ContentValues();
2102b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        extended.put(CalendarContract.ExtendedProperties.VALUE, "baz");
21037e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21040739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("update", 1, mResolver.update(
21050739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(extendedUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
21060739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                extended,
21077e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
21087e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2109b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI, "event_id=" + eventId, 2);
21107e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21117e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Now test deletes
21127e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21137e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        assertEquals("delete", 1, mResolver.delete(
21140739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(attendeeUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
21157e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null, null /* selectionArgs */));
21167e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2117b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Attendees.CONTENT_URI, "event_id=" + eventId, 0);
21187e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21190739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("delete", 1, mResolver.delete(
21200739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(reminderUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
21217e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
21227e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21237e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2124b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Reminders.CONTENT_URI, "event_id=" + eventId, 0);
21257e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21260739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("delete", 1, mResolver.delete(
21270739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(alertUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
21287e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                null /* where */, null /* selectionArgs */));
21297e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21307e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Alerts don't dirty the event
21317e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 0);
2132b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.CalendarAlerts.CONTENT_URI, "event_id=" + eventId, 0);
21337e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21340739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik        assertEquals("delete", 1, mResolver.delete(
21350739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(extendedUri, syncAdapter, DEFAULT_ACCOUNT, DEFAULT_ACCOUNT_TYPE),
2136205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff                null /* where */, null /* selectionArgs */));
2137205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
2138205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        testAndClearDirty(eventId, syncAdapter ? 0 : 1);
2139b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.ExtendedProperties.CONTENT_URI, "event_id=" + eventId, 1);
21407e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
21417e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
21427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
21437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * Test calendar deletion
21447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @throws Exception
21457e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     */
21467e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    public void testCalendarDeletion() throws Exception {
21477e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
21487e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri eventUri = insertEvent(mCalendarId, findEvent("daily0"));
21497e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId = ContentUris.parseId(eventUri);
21507e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        testAndClearDirty(eventId, 1);
21517e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        Uri eventUri1 = insertEvent(mCalendarId, findEvent("daily1"));
21527e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        long eventId1 = ContentUris.parseId(eventUri);
21537e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        assertEquals("delete", 1, mResolver.delete(eventUri1, null, null));
21547e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Calendar has one event and one deleted event
2155b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
21567e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
2157b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        assertEquals("delete", 1, mResolver.delete(CalendarContract.Calendars.CONTENT_URI,
21587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                "_id=" + mCalendarId, null));
21597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Calendar should be deleted
2160b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null, 0);
21617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        // Event should be gone
2162b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 0);
2163205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    }
2164205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
2165205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    /**
2166205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff     * Test multiple account support.
2167205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff     */
2168205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff    public void testMultipleAccounts() throws Exception {
2169205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2170205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        int calendarId1 = insertCal("Calendar1", DEFAULT_TIMEZONE, "user2@google.com");
2171205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        Uri eventUri0 = insertEvent(mCalendarId, findEvent("daily0"));
217283c55844974ca611a553e704663ed845d84c7930Ken Shirriff        Uri eventUri1 = insertEvent(calendarId1, findEvent("daily1"));
2173205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff
2174b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
2175b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri eventsWithAccount = CalendarContract.Events.CONTENT_URI.buildUpon()
2176b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .appendQueryParameter(CalendarContract.EventsEntity.ACCOUNT_NAME, DEFAULT_ACCOUNT)
2177b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .appendQueryParameter(CalendarContract.EventsEntity.ACCOUNT_TYPE,
2178b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        DEFAULT_ACCOUNT_TYPE)
2179205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff                .build();
2180205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        // Only one event for that account
2181205fe71b416fe4a742310dabed5e813946afc999Ken Shirriff        testQueryCount(eventsWithAccount, null, 1);
21821ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff
21831ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Test deletion with account and selection
21841ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff
21851ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        long eventId = ContentUris.parseId(eventUri1);
21861ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Wrong account, should not be deleted
21871ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        assertEquals("delete", 0, mResolver.delete(
21880739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                updatedUri(eventsWithAccount, true /* syncAdapter */, DEFAULT_ACCOUNT,
21890739be04415dfd61619b5611e82b7c9a6c83eae3RoboErik                        DEFAULT_ACCOUNT_TYPE),
21901ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff                "_id=" + eventId, null /* selectionArgs */));
2191b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 2);
21921ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        // Right account, should be deleted
21931ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff        assertEquals("delete", 1, mResolver.delete(
2194b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                updatedUri(CalendarContract.Events.CONTENT_URI, true /* syncAdapter */,
2195b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        "user2@google.com", DEFAULT_ACCOUNT_TYPE),
21961ae4c22f15c107cd9f9cd8babaa11005e45e4647Ken Shirriff                "_id=" + eventId, null /* selectionArgs */));
2197b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null, 1);
21987e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
21997e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
22007e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /**
22019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run commands, wiping instance table at each step.
22029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This tests full instance expansion.
22039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
22049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
22059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testCommandSequences1() throws Exception {
22069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commandSequences(true);
22079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
22089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
22109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run commands normally.
22119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * This tests incremental instance expansion.
22129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
22139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
22149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testCommandSequences2() throws Exception {
22159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commandSequences(false);
22169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
22179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
22199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Run thorough set of command sequences
22209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param wipe true if instances should be wiped and regenerated
22219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
22229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
22239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void commandSequences(boolean wipe) throws Exception {
22249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Cursor cursor;
22259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Uri url = null;
22269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mWipe = wipe; // Set global flag
22279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
22299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor = mResolver.query(mEventsUri, null, null, null, null);
22319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(0, cursor.getCount());
22329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        cursor.close();
22339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Command[] commands;
22349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Normal insert/delete");
22369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mNormalInsertDelete;
22379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "All-day insert/delete");
22449f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mAlldayInsertDelete;
22459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Recurring insert/delete");
22529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mRecurringInsertDelete;
22539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with truncated recurrence");
22609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithTruncatedRecurrence;
22619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with moved recurrence");
22689f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithMovedRecurrence;
22699f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with cancel");
22769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mCancelInstance;
22779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with moved recurrence2");
22849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithMovedRecurrence2;
22859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        deleteAllEvents();
22909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Exception with no recurrence");
22929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        commands = mExceptionWithNoRecurrence;
22939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        for (Command command : commands) {
22949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            command.execute();
22959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
22969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
22979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
22989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
22999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Test Time toString.
23009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @throws Exception
23019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
23029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // Suppressed because toString currently hangs.
23039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Suppress
23049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void testTimeToString() throws Exception {
23059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Time time = new Time(Time.TIMEZONE_UTC);
23069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String str = "2039-01-01T23:00:00.000Z";
23079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        String result = "20390101T230000UTC(0,0,0,-1,0)";
23089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        time.parse3339(str);
23099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        assertEquals(result, time.toString());
23109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
23119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2312c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    /**
2313c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     * Test the query done by Event.loadEvents
2314bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Also test that instance queries work when an event straddles the expansion range
2315c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     * @throws Exception
2316c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff     */
2317c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    public void testInstanceQuery() throws Exception {
2318c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        final String[] PROJECTION = new String[] {
2319c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.TITLE,                 // 0
2320c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_LOCATION,        // 1
2321c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.ALL_DAY,               // 2
2322bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden                Instances.CALENDAR_COLOR,        // 3
2323c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_TIMEZONE,        // 4
2324c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.EVENT_ID,              // 5
2325c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.BEGIN,                 // 6
2326c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END,                   // 7
2327c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances._ID,                   // 8
2328c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.START_DAY,             // 9
2329c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END_DAY,               // 10
2330c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.START_MINUTE,          // 11
2331c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.END_MINUTE,            // 12
2332c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.HAS_ALARM,             // 13
2333c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.RRULE,                 // 14
2334c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.RDATE,                 // 15
2335c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Instances.SELF_ATTENDEE_STATUS,  // 16
2336c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Events.ORGANIZER,                // 17
2337c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff                Events.GUESTS_CAN_MODIFY,        // 18
2338c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff        };
2339c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
23402ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik        String orderBy = CalendarProvider2.SORT_CALENDAR_VIEW;
2341b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        String where = Instances.SELF_ATTENDEE_STATUS + "!="
2342b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED;
2343c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
2344975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2345975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        final String START = "2008-05-01T00:00:00";
2346975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        final String END = "2008-05-01T20:00:00";
2347975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2348975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        EventInfo[] events = { new EventInfo("normal0",
2349975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                START,
2350975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                END,
2351975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                false /* allDay */,
2352975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                DEFAULT_TIMEZONE) };
2353975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2354975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        insertEvent(calId, events[0]);
2355975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2356975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        Time time = new Time(DEFAULT_TIMEZONE);
2357975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        time.parse3339(START);
2358975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        long startMs = time.toMillis(true /* ignoreDst */);
2359975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Query starting from way in the past to one hour into the event.
2360975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Query is more than 2 months so the range won't get extended by the provider.
2361975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        Cursor cursor = Instances.query(mResolver, PROJECTION,
2362975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                startMs - DateUtils.YEAR_IN_MILLIS, startMs + DateUtils.HOUR_IN_MILLIS,
23632ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                where, null, orderBy);
2364975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        try {
2365975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            assertEquals(1, cursor.getCount());
2366975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        } finally {
2367975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            cursor.close();
2368975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        }
2369975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff
2370975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        // Now expand the instance range.  The event overlaps the new part of the range.
2371975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        cursor = Instances.query(mResolver, PROJECTION,
2372975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff                startMs - DateUtils.YEAR_IN_MILLIS, startMs + 2 * DateUtils.HOUR_IN_MILLIS,
23732ce7955da7dffec7819ed38be85e72df8a6f33dcRoboErik                where, null, orderBy);
2374975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        try {
2375975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            assertEquals(1, cursor.getCount());
2376975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        } finally {
2377975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff            cursor.close();
2378975efd902429cd72cf1bfabf8663e1893c84a624Ken Shirriff        }
2379c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff    }
2380c07771fcc66414d8f266f969bb63670391a17bb8Ken Shirriff
23819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private Cursor queryInstances(long begin, long end) {
2382b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri url = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_URI, begin + "/" + end);
23839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mResolver.query(url, null, null, null, null);
23849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
23859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
23869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    protected static class MockProvider extends ContentProvider {
23879f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
23889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        private String mAuthority;
23899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
23909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        private int mNumItems = 0;
23919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
23929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public MockProvider(String authority) {
23939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mAuthority = authority;
23949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
23959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
23969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
23979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public boolean onCreate() {
23989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return true;
23999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
24029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Cursor query(Uri uri, String[] projection, String selection,
24039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String[] selectionArgs, String sortOrder) {
24049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return new ArrayListCursor(new String[]{}, new ArrayList<ArrayList>());
24059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
24089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public String getType(Uri uri) {
24099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            throw new UnsupportedOperationException();
24109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
24139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public Uri insert(Uri uri, ContentValues values) {
24149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            mNumItems++;
24159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return Uri.parse("content://" + mAuthority + "/" + mNumItems);
24169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
24199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public int delete(Uri uri, String selection, String[] selectionArgs) {
24209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return 0;
24219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
24239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        @Override
24249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        public int update(Uri uri, ContentValues values, String selection,
24259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                String[] selectionArgs) {
24269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            return 0;
24279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
24289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2429ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2430ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void cleanCalendarDataTable(SQLiteOpenHelper helper) {
2431ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        if (null == helper) {
2432ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            return;
2433ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2434ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        SQLiteDatabase db = helper.getWritableDatabase();
2435ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        db.execSQL("DELETE FROM CalendarCache;");
2436ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2437ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2438ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    public void testGetAndSetTimezoneDatabaseVersion() throws CalendarCache.CacheException {
2439ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2440ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cleanCalendarDataTable(helper);
2441ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2442ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2443ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        boolean hasException = false;
2444ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        try {
2445ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            String value = cache.readData(null);
2446ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        } catch (CalendarCache.CacheException e) {
2447ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            hasException = true;
2448ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2449ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertTrue(hasException);
2450ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2451ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertNull(cache.readTimezoneDatabaseVersion());
2452ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2453ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cache.writeTimezoneDatabaseVersion("1234");
2454ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals("1234", cache.readTimezoneDatabaseVersion());
2455ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2456ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cache.writeTimezoneDatabaseVersion("5678");
2457ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals("5678", cache.readTimezoneDatabaseVersion());
2458ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2459ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2460ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void checkEvent(int eventId, String title, long dtStart, long dtEnd, boolean allDay) {
2461b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Uri uri = Uri.parse("content://" + CalendarContract.AUTHORITY + "/events");
2462ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Log.i(TAG, "Looking for EventId = " + eventId);
2463ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2464ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Cursor cursor = mResolver.query(uri, null, null, null, null);
2465ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(1, cursor.getCount());
2466ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2467b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexTitle = cursor.getColumnIndex(CalendarContract.Events.TITLE);
2468b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexDtStart = cursor.getColumnIndex(CalendarContract.Events.DTSTART);
2469b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexDtEnd = cursor.getColumnIndex(CalendarContract.Events.DTEND);
2470b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        int colIndexAllDay = cursor.getColumnIndex(CalendarContract.Events.ALL_DAY);
2471ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        if (!cursor.moveToNext()) {
2472ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            Log.e(TAG,"Could not find inserted event");
2473ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio            assertTrue(false);
2474ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        }
2475ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(title, cursor.getString(colIndexTitle));
2476ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(dtStart, cursor.getLong(colIndexDtStart));
2477ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(dtEnd, cursor.getLong(colIndexDtEnd));
2478ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(allDay, (cursor.getInt(colIndexAllDay) != 0));
2479ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cursor.close();
2480ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2481ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2482ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    public void testChangeTimezoneDB() {
2483ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
2484ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2485b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver
2486b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                .query(CalendarContract.Events.CONTENT_URI, null, null, null, null);
2487ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(0, cursor.getCount());
2488ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        cursor.close();
2489ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2490ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        EventInfo[] events = { new EventInfo("normal0",
2491ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        "2008-05-01T00:00:00",
2492ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        "2008-05-02T00:00:00",
2493ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        false,
2494ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                                        DEFAULT_TIMEZONE) };
2495ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2496ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        Uri uri = insertEvent(calId, events[0]);
2497ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertNotNull(uri);
2498ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2499ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // check the inserted event
2500ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        checkEvent(1, events[0].mTitle, events[0].mDtstart, events[0].mDtend, events[0].mAllDay);
2501ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2502ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // inject a new time zone
2503ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        getProvider().doProcessEventRawTimes(TIME_ZONE_AMERICA_ANCHORAGE,
2504ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                MOCK_TIME_ZONE_DATABASE_VERSION);
2505ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2506ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        // check timezone database version
2507ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio        assertEquals(MOCK_TIME_ZONE_DATABASE_VERSION, getProvider().getTimezoneDatabaseVersion());
2508ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
25093443e3ebeaa39e8415b43e7cf3b218caee554e9bFabrice Di Meglio        // check that the inserted event has *not* been updated
25103443e3ebeaa39e8415b43e7cf3b218caee554e9bFabrice Di Meglio        checkEvent(1, events[0].mTitle, events[0].mDtstart, events[0].mDtend, events[0].mAllDay);
2511ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2512315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2513315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public static final Uri PROPERTIES_CONTENT_URI =
2514b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            Uri.parse("content://" + CalendarContract.AUTHORITY + "/properties");
2515315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2516315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public static final int COLUMN_KEY_INDEX = 1;
2517315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public static final int COLUMN_VALUE_INDEX = 0;
2518315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2519315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testGetProviderProperties() throws CalendarCache.CacheException {
2520315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2521315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2522315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2523315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2524315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2525315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Denver");
2526315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Los_Angeles");
2527315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2528315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2529315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Cursor cursor = mResolver.query(PROPERTIES_CONTENT_URI, null, null, null, null);
2530315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(4, cursor.getCount());
2531315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2532315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(CalendarCache.COLUMN_NAME_KEY, cursor.getColumnName(COLUMN_KEY_INDEX));
2533315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(CalendarCache.COLUMN_NAME_VALUE, cursor.getColumnName(COLUMN_VALUE_INDEX));
2534315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2535315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Map<String, String> map = new HashMap<String, String>();
2536315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2537315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        while (cursor.moveToNext()) {
2538315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            String key = cursor.getString(COLUMN_KEY_INDEX);
2539315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            String value = cursor.getString(COLUMN_VALUE_INDEX);
2540315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            map.put(key, value);
2541315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        }
2542315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2543315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_DATABASE_VERSION));
2544315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_TYPE));
2545315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_INSTANCES));
2546315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(map.containsKey(CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS));
2547315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2548315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("2010k", map.get(CalendarCache.KEY_TIMEZONE_DATABASE_VERSION));
2549315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("America/Denver", map.get(CalendarCache.KEY_TIMEZONE_INSTANCES));
2550315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals("America/Los_Angeles", map.get(CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS));
2551315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(CalendarCache.TIMEZONE_TYPE_AUTO, map.get(CalendarCache.KEY_TIMEZONE_TYPE));
2552315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2553315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cursor.close();
2554315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2555315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2556315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testGetProviderPropertiesByKey() throws CalendarCache.CacheException {
2557315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2558315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2559315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2560315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2561315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2562315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Denver");
2563315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Los_Angeles");
2564315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2565315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2566315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(CalendarCache.TIMEZONE_TYPE_AUTO, CalendarCache.KEY_TIMEZONE_TYPE);
2567315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("2010k", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2568315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES);
2569315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Los_Angeles", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2570315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2571315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2572315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void checkValueForKey(String value, String key) {
2573315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        Cursor cursor = mResolver.query(PROPERTIES_CONTENT_URI, null,
2574315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "key=?", new String[] {key}, null);
2575315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2576315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(1, cursor.getCount());
2577315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertTrue(cursor.moveToFirst());
2578315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(cursor.getString(COLUMN_KEY_INDEX), key);
2579315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(cursor.getString(COLUMN_VALUE_INDEX), value);
2580315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2581315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cursor.close();
2582315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2583315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2584315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    public void testUpdateProviderProperties() throws CalendarCache.CacheException {
2585315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarDatabaseHelper helper = (CalendarDatabaseHelper) getProvider().getDatabaseHelper();
2586315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cleanCalendarDataTable(helper);
2587315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        CalendarCache cache = new CalendarCache(helper);
2588315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2589315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String localTimezone = TimeZone.getDefault().getID();
2590315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2591315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial value
2592315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneDatabaseVersion("2010k");
2593315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2594315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey("2009s", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2595315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("2009s", CalendarCache.KEY_TIMEZONE_DATABASE_VERSION);
2596315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2597315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial values
2598315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneType(CalendarCache.TIMEZONE_TYPE_AUTO);
2599315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstances("America/Chicago");
2600315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("America/Denver");
2601315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2602315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(CalendarCache.TIMEZONE_TYPE_AUTO, CalendarCache.KEY_TIMEZONE_TYPE);
2603315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2604315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2605315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2606315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(CalendarCache.TIMEZONE_TYPE_HOME, CalendarCache.KEY_TIMEZONE_TYPE);
2607315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES);
2608315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey("America/Denver", CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2609315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2610315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set initial value
2611315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        cache.writeTimezoneInstancesPrevious("");
2612315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2613315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES);
2614315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        checkValueForKey(localTimezone, CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS);
2615315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2616315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2617315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void updateValueForKey(String value, String key) {
2618315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        ContentValues contentValues = new ContentValues();
2619315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        contentValues.put(CalendarCache.COLUMN_NAME_VALUE, value);
2620315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2621315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        int result = mResolver.update(PROPERTIES_CONTENT_URI,
2622315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                contentValues,
2623315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + "=?",
2624315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                new String[] {key});
2625315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2626315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        assertEquals(1, result);
2627315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
26288ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26298ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio    public void testInsertOriginalTimezoneInExtProperties() throws Exception {
26308ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
26318ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26328ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26338ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        EventInfo[] events = { new EventInfo("normal0",
26348ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                                        "2008-05-01T00:00:00",
26358ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                                        "2008-05-02T00:00:00",
26368ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                                        false,
26378ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                                        DEFAULT_TIMEZONE) };
26388ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26398ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        Uri eventUri = insertEvent(calId, events[0]);
26408ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        assertNotNull(eventUri);
26418ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26428ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        long eventId = ContentUris.parseId(eventUri);
26438ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        assertTrue(eventId > -1);
26448ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26458ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        // check the inserted event
26468ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        checkEvent(1, events[0].mTitle, events[0].mDtstart, events[0].mDtend, events[0].mAllDay);
26478ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26488ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        // Should have 1 calendars and 1 event
2649b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Calendars.CONTENT_URI, null /* where */, 1);
2650b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        testQueryCount(CalendarContract.Events.CONTENT_URI, null /* where */, 1);
26518ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26528ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        // Verify that the original timezone is correct
2653b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        Cursor cursor = mResolver.query(CalendarContract.ExtendedProperties.CONTENT_URI,
26548ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                null/* projection */,
26558ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                "event_id=" + eventId,
26568ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                null /* selectionArgs */,
26578ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                null /* sortOrder */);
26588ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        try {
26598ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio            // Should have 1 extended property for the original timezone
26608ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio            assertEquals(1, cursor.getCount());
26618ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26628ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio            if (cursor.moveToFirst()) {
26638ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                long id = cursor.getLong(0);
26648ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                assertEquals(id, eventId);
26658ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio
26668ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                assertEquals(CalendarProvider2.EXT_PROP_ORIGINAL_TIMEZONE, cursor.getString(2));
26678ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio                assertEquals(DEFAULT_TIMEZONE, cursor.getString(3));
26688ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio            }
26698ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        } finally {
26708ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio            cursor.close();
26718ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio        }
26728ba0d0238b153d331d612078b19492cb44728101Fabrice Di Meglio    }
267374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
2674bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    /**
2675bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * Verifies that the number of defined calendars meets expectations.
2676bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     *
2677bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     * @param expectedCount The number of calendars we expect to find.
2678bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden     */
267974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarCount(int expectedCount) {
268074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        Cursor cursor = mResolver.query(mCalendarsUri,
268174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* projection */,
268274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selection */,
268374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selectionArgs */,
268474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* sortOrder */);
268574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertEquals(expectedCount, cursor.getCount());
268674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        cursor.close();
268774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
268874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
268974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarExists(int calId) {
269074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertTrue(isCalendarExists(calId));
269174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
269274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
269374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private void checkCalendarDoesNotExists(int calId) {
269474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        assertFalse(isCalendarExists(calId));
269574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
269674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
269774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    private boolean isCalendarExists(int calId) {
269874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        Cursor cursor = mResolver.query(mCalendarsUri,
269974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] {Calendars._ID},
270074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selection */,
270174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* selectionArgs */,
270274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                null /* sortOrder */);
270374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        boolean found = false;
270474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        while (cursor.moveToNext()) {
270574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio            if (calId == cursor.getInt(0)) {
270674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                found = true;
270774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                break;
270874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio            }
270974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        }
271074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        cursor.close();
271174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        return found;
271274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
271374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
271474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteAllCalendars() {
271574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
271674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
271774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        insertCal("Calendar1", "America/Los_Angeles");
271874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        insertCal("Calendar2", "America/Los_Angeles");
271974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
272074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
272174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
272274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(null /* selection */, null /* selectionArgs*/);
272374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
272474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
272574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
272674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteCalendarsWithSelection() {
272774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
272874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
272974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId1 = insertCal("Calendar1", "America/Los_Angeles");
273074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId2 = insertCal("Calendar2", "America/Los_Angeles");
273174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
273274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
273374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
273474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId2);
273574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
273674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=" + calId2, null /* selectionArgs*/);
273774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(1);
273874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
273974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarDoesNotExists(calId2);
274074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
274174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
274274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    public void testDeleteCalendarsWithSelectionAndArgs() {
274374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
274474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
274574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId1 = insertCal("Calendar1", "America/Los_Angeles");
274674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        int calId2 = insertCal("Calendar2", "America/Los_Angeles");
274774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
274874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(2);
274974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
275074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId2);
275174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
275274ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=?",
275374ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] { Integer.toString(calId2) });
275474ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(1);
275574ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarExists(calId1);
275674ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarDoesNotExists(calId2);
275774ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio
275874ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        deleteMatchingCalendars(Calendars._ID + "=?" + " AND " + Calendars.NAME + "=?",
275974ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio                new String[] { Integer.toString(calId1), "Calendar1" });
276074ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio        checkCalendarCount(0);
276174ca9ba319a55a7dcb222344d2582e4dabe5d3bfFabrice Di Meglio    }
27629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff}
2763