CalendarProviderTestpublic class CalendarProviderTest extends android.test.ProviderTestCase2 Runs various tests on an isolated Calendar provider with its own database. |
Fields Summary |
---|
static final String | TAG | static final String | DEFAULT_TIMEZONE | private android.database.sqlite.SQLiteDatabase | mDb | private MetaData | mMetaData | private android.content.Context | mContext | private android.test.mock.MockContentResolver | mResolver | private android.net.Uri | mEventsUri | private int | mCalendarId | private int | mGlobalSyncId | private EventInfo[] | mEventsThis is the main table of events. The events in this table are
referred to by name in other places. | private InstanceInfo[] | mInstanceRangesThis table is used to create repeating events and then check that the
number of instances within a given range matches the expected number
of instances. | private EventInfo[] | mBusyBitEventsThis tables of events is used to test the BusyBit database table. | private EventInfo[] | mBusyBitRepeatingEvents | private BusyBitInfo[] | mBusyBitTests | private Command[] | mNormalInsertDeleteThis sequence of commands inserts and deletes some events. | private Command[] | mAlldayInsertDeleteThis sequence of commands inserts and deletes some all-day events. | private Command[] | mRecurringInsertDeleteThis sequence of commands inserts and deletes some repeating events. | private Command[] | mExceptionWithMovedRecurrenceThis sequence of commands creates a recurring event with a recurrence
exception that moves an event outside the expansion window. It checks that the
recurrence exception does not occur in the Instances database table.
Bug 1642665 | private Command[] | mExceptionWithTruncatedRecurrenceThis sequence of commands creates a recurring event with a recurrence
exception and then changes the end time of the recurring event. It then
checks that the recurrence exception does not occur in the Instances
database table. | private Command[] | mExceptionWithNoRecurrenceBug 135848. Ensure that a recurrence exception is displayed even if the recurrence
is not present. |
Constructors Summary |
---|
public CalendarProviderTest()
super(CalendarProvider.class, Calendar.AUTHORITY);
|
Methods Summary |
---|
private void | deleteAllEvents()
mDb.execSQL("DELETE FROM Events;");
mMetaData.clearInstanceRange();
| private int | deleteMatchingEvents(java.lang.String title)Deletes all the events that match the given title.
Cursor cursor = mResolver.query(mEventsUri, new String[] { Events._ID },
"title=?", new String[] { title }, null);
int numRows = 0;
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
numRows += mResolver.delete(uri, null, null);
}
cursor.close();
return numRows;
| private void | dumpCursor(android.database.Cursor cursor)Dumps the contents of the given cursor to the log. For debugging.
String[] cols = cursor.getColumnNames();
Log.i(TAG, "dumpCursor() count: " + cursor.getCount());
int index = 0;
while (cursor.moveToNext()) {
Log.i(TAG, index + " {");
for (int i = 0; i < cols.length; i++) {
Log.i(TAG, " " + cols[i] + '=" + cursor.getString(i));
}
Log.i(TAG, "}");
index += 1;
}
| private com.android.providers.calendar.CalendarProviderTest$EventInfo | findEvent(java.lang.String name)
int len = mEvents.length;
for (int ii = 0; ii < len; ii++) {
EventInfo event = mEvents[ii];
if (name.equals(event.mTitle)) {
return event;
}
}
return null;
| private int | insertCal(java.lang.String name, java.lang.String timezone)
ContentValues m = new ContentValues();
m.put(Calendars.NAME, name);
m.put(Calendars.DISPLAY_NAME, name);
m.put(Calendars.COLOR, "0xff123456");
m.put(Calendars.TIMEZONE, timezone);
m.put(Calendars.SELECTED, 1);
Uri url = mResolver.insert(Uri.parse("content://calendar/calendars"), m);
String id = url.getLastPathSegment();
return Integer.parseInt(id);
| private android.net.Uri | insertEvent(int calId, com.android.providers.calendar.CalendarProviderTest$EventInfo event)
ContentValues m = new ContentValues();
m.put(Events.CALENDAR_ID, calId);
m.put(Events.TITLE, event.mTitle);
m.put(Events.DTSTART, event.mDtstart);
m.put(Events.ALL_DAY, event.mAllDay ? 1 : 0);
if (event.mRrule == null) {
// This is a normal event
m.put(Events.DTEND, event.mDtend);
} else {
// This is a repeating event
m.put(Events.RRULE, event.mRrule);
m.put(Events.DURATION, event.mDuration);
}
if (event.mDescription != null) {
m.put(Events.DESCRIPTION, event.mDescription);
}
if (event.mTimezone != null) {
m.put(Events.EVENT_TIMEZONE, event.mTimezone);
}
if (event.mOriginalTitle != null) {
// This is a recurrence exception.
EventInfo recur = findEvent(event.mOriginalTitle);
assertNotNull(recur);
String syncId = String.format("%d", recur.mSyncId);
m.put(Events.ORIGINAL_EVENT, syncId);
m.put(Events.ORIGINAL_ALL_DAY, recur.mAllDay ? 1 : 0);
m.put(Events.ORIGINAL_INSTANCE_TIME, event.mOriginalInstance);
}
Uri url = mResolver.insert(mEventsUri, m);
// Create a fake _sync_id and add it to the event. Update the database
// directly so that we don't trigger any validation checks in the
// CalendarProvider.
long id = ContentUris.parseId(url);
mDb.execSQL("UPDATE Events SET _sync_id=" + mGlobalSyncId + " WHERE _id=" + id);
event.mSyncId = mGlobalSyncId;
mGlobalSyncId += 1;
return url;
| private android.database.Cursor | queryBusyBits(int startDay, int numDays)
int endDay = startDay + numDays - 1;
Uri url = Uri.parse("content://calendar/busybits/when/" + startDay + "/" + endDay);
return mResolver.query(url, null, null, null, null);
| private android.database.Cursor | queryInstances(long begin, long end)
Uri url = Uri.parse("content://calendar/instances/when/" + begin + "/" + end);
return mResolver.query(url, null, null, null, null);
| protected void | setUp()
super.setUp();
mContext = getMockContext();
mResolver = getMockContentResolver();
mResolver.addProvider("subscribedfeeds", new MockProvider("subscribedfeeds"));
mResolver.addProvider("sync", new MockProvider("sync"));
mDb = getProvider().getDatabase();
mMetaData = getProvider().mMetaData;
| protected void | tearDown()
super.tearDown();
| public void | testBusyBitRange()
Cursor cursor;
Uri url = null;
int calId = insertCal("Calendar0", "America/Los_Angeles");
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
int len = mBusyBitTests.length;
for (int ii = 0; ii < len; ii++) {
deleteAllEvents();
BusyBitInfo busyInfo = mBusyBitTests[ii];
EventInfo[] events = busyInfo.mEvents;
int numEvents = events.length;
for (int jj = 0; jj < numEvents; jj++) {
EventInfo event = events[jj];
insertEvent(calId, event);
}
int startDay = busyInfo.mStartDay;
int numDays = busyInfo.mNumDays;
int[] busybits = new int[numDays];
int[] allDayCounts = new int[numDays];
if (false) {
cursor = mResolver.query(mEventsUri, null, null, null, null);
Log.i(TAG, "Dump of Events table, count: " + cursor.getCount());
dumpCursor(cursor);
cursor.close();
Time time = new Time();
time.setJulianDay(startDay);
long begin = time.toMillis(true);
int endDay = startDay + numDays - 1;
time.setJulianDay(endDay);
long end = time.toMillis(true);
cursor = queryInstances(begin, end);
Log.i(TAG, "Dump of Instances table, count: " + cursor.getCount()
+ " startDay: " + startDay + " endDay: " + endDay
+ " begin: " + begin + " end: " + end);
dumpCursor(cursor);
cursor.close();
}
cursor = queryBusyBits(startDay, numDays);
try {
int dayColumnIndex = cursor.getColumnIndexOrThrow(BusyBits.DAY);
int busybitColumnIndex = cursor.getColumnIndexOrThrow(BusyBits.BUSYBITS);
int allDayCountColumnIndex = cursor.getColumnIndexOrThrow(BusyBits.ALL_DAY_COUNT);
while (cursor.moveToNext()) {
int day = cursor.getInt(dayColumnIndex);
int dayIndex = day - startDay;
busybits[dayIndex] = cursor.getInt(busybitColumnIndex);
allDayCounts[dayIndex] = cursor.getInt(allDayCountColumnIndex);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
// Compare the database busy bits with the expected busy bits
for (int dayIndex = 0; dayIndex < numDays; dayIndex++) {
if (busyInfo.mBusyBits[dayIndex] != busybits[dayIndex]) {
String mesg = String.format("Test failed!"
+ " BusyBit test index: %d"
+ " day index: %d"
+ " mStartDay: %d mNumDays: %d"
+ " expected busybits: 0x%x was: 0x%x",
ii, dayIndex, busyInfo.mStartDay, busyInfo.mNumDays,
busyInfo.mBusyBits[dayIndex], busybits[dayIndex]);
Log.e(TAG, mesg);
cursor = mResolver.query(mEventsUri, null, null, null, null);
Log.i(TAG, "Dump of Events table, count: " + cursor.getCount());
dumpCursor(cursor);
cursor.close();
}
assertEquals(busyInfo.mBusyBits[dayIndex], busybits[dayIndex]);
}
// Compare the database all-day counts with the expected all-day counts
for (int dayIndex = 0; dayIndex < numDays; dayIndex++) {
if (busyInfo.mAllDayCounts[dayIndex] != allDayCounts[dayIndex]) {
String mesg = String.format("Test failed!"
+ " BusyBit test index: %d"
+ " day index: %d"
+ " expected all-day count: %d was: %d",
ii, dayIndex,
busyInfo.mAllDayCounts[dayIndex], allDayCounts[dayIndex]);
Log.e(TAG, mesg);
}
assertEquals(busyInfo.mAllDayCounts[dayIndex], allDayCounts[dayIndex]);
}
}
| public void | testCommandSequences()
Cursor cursor;
Uri url = null;
mCalendarId = insertCal("Calendar0", DEFAULT_TIMEZONE);
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
Log.i(TAG, "Normal insert/delete");
Command[] commands = mNormalInsertDelete;
for (Command command : commands) {
command.execute();
}
deleteAllEvents();
Log.i(TAG, "All-day insert/delete");
commands = mAlldayInsertDelete;
for (Command command : commands) {
command.execute();
}
deleteAllEvents();
Log.i(TAG, "Recurring insert/delete");
commands = mRecurringInsertDelete;
for (Command command : commands) {
command.execute();
}
deleteAllEvents();
Log.i(TAG, "Exception with truncated recurrence");
commands = mExceptionWithTruncatedRecurrence;
for (Command command : commands) {
command.execute();
}
deleteAllEvents();
Log.i(TAG, "Exception with moved recurrence");
commands = mExceptionWithMovedRecurrence;
for (Command command : commands) {
command.execute();
}
deleteAllEvents();
Log.i(TAG, "Exception with no recurrence");
commands = mExceptionWithNoRecurrence;
for (Command command : commands) {
command.execute();
}
| public void | testInsertNormalEvents()
Cursor cursor;
Uri url = null;
int calId = insertCal("Calendar0", DEFAULT_TIMEZONE);
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
// Keep track of the number of normal events
int numEvents = 0;
// "begin" is the earliest start time of all the normal events,
// and "end" is the latest end time of all the normal events.
long begin = 0, end = 0;
int len = mEvents.length;
for (int ii = 0; ii < len; ii++) {
EventInfo event = mEvents[ii];
// Skip repeating events and recurrence exceptions
if (event.mRrule != null || event.mOriginalTitle != null) {
continue;
}
if (numEvents == 0) {
begin = event.mDtstart;
end = event.mDtend;
} else {
if (begin > event.mDtstart) {
begin = event.mDtstart;
}
if (end < event.mDtend) {
end = event.mDtend;
}
}
url = insertEvent(calId, event);
numEvents += 1;
}
// query one
cursor = mResolver.query(url, null, null, null, null);
assertEquals(1, cursor.getCount());
cursor.close();
// query all
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(numEvents, cursor.getCount());
cursor.close();
// Check that the Instances table has one instance of each of the
// normal events.
cursor = queryInstances(begin, end);
assertEquals(numEvents, cursor.getCount());
cursor.close();
| public void | testInsertRepeatingEvents()
Cursor cursor;
Uri url = null;
int calId = insertCal("Calendar0", "America/Los_Angeles");
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
// Keep track of the number of repeating events
int numEvents = 0;
int len = mEvents.length;
for (int ii = 0; ii < len; ii++) {
EventInfo event = mEvents[ii];
// Skip normal events
if (event.mRrule == null) {
continue;
}
url = insertEvent(calId, event);
numEvents += 1;
}
// query one
cursor = mResolver.query(url, null, null, null, null);
assertEquals(1, cursor.getCount());
cursor.close();
// query all
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(numEvents, cursor.getCount());
cursor.close();
| public void | testInstanceRange()
Cursor cursor;
Uri url = null;
int calId = insertCal("Calendar0", "America/Los_Angeles");
cursor = mResolver.query(mEventsUri, null, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
int len = mInstanceRanges.length;
for (int ii = 0; ii < len; ii++) {
InstanceInfo instance = mInstanceRanges[ii];
EventInfo event = instance.mEvent;
url = insertEvent(calId, event);
cursor = queryInstances(instance.mBegin, instance.mEnd);
if (instance.mExpectedOccurrences != cursor.getCount()) {
Log.e(TAG, "Test failed! Instance index: " + ii);
Log.e(TAG, "title: " + event.mTitle + " desc: " + event.mDescription
+ " [begin,end]: [" + instance.mBegin + " " + instance.mEnd + "]"
+ " expected: " + instance.mExpectedOccurrences);
dumpCursor(cursor);
}
assertEquals(instance.mExpectedOccurrences, cursor.getCount());
cursor.close();
int rows = mResolver.delete(url, null /* selection */, null /* selection args */);
assertEquals(1, rows);
}
| private int | updateMatchingEvents(java.lang.String title, android.content.ContentValues values)Updates all the events that match the given title.
String[] projection = new String[] {
Events._ID,
Events.DTSTART,
Events.DTEND,
Events.DURATION,
Events.ALL_DAY,
Events.RRULE,
Events.EVENT_TIMEZONE,
};
Cursor cursor = mResolver.query(mEventsUri, projection,
"title=?", new String[] { title }, null);
int numRows = 0;
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
// If any of the following fields are being changed, then we need
// to include all of them.
if (values.containsKey(Events.DTSTART) || values.containsKey(Events.DTEND)
|| values.containsKey(Events.DURATION) || values.containsKey(Events.ALL_DAY)
|| values.containsKey(Events.RRULE)
|| values.containsKey(Events.EVENT_TIMEZONE)) {
long dtstart = cursor.getLong(1);
long dtend = cursor.getLong(2);
String duration = cursor.getString(3);
boolean allDay = cursor.getInt(4) != 0;
String rrule = cursor.getString(5);
String timezone = cursor.getString(6);
if (!values.containsKey(Events.DTSTART)) {
values.put(Events.DTSTART, dtstart);
}
// Don't add DTEND for repeating events
if (!values.containsKey(Events.DTEND) && rrule == null) {
values.put(Events.DTEND, dtend);
}
if (!values.containsKey(Events.DURATION) && duration != null) {
values.put(Events.DURATION, duration);
}
if (!values.containsKey(Events.ALL_DAY)) {
values.put(Events.ALL_DAY, allDay ? 1 : 0);
}
if (!values.containsKey(Events.RRULE) && rrule != null) {
values.put(Events.RRULE, rrule);
}
if (!values.containsKey(Events.EVENT_TIMEZONE) && timezone != null) {
values.put(Events.EVENT_TIMEZONE, timezone);
}
}
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, id);
numRows += mResolver.update(uri, values, null, null);
}
cursor.close();
return numRows;
|
|