blob: d469852b268f49ecaccdfaa546f225ea36bc9c6c [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.providers.calendar;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.provider.Calendar;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
import android.util.Log;
import junit.framework.TestCase;
public class CalendarDatabaseHelperTest extends TestCase {
private SQLiteDatabase mBadDb;
private SQLiteDatabase mGoodDb;
private DatabaseUtils.InsertHelper mBadEventsInserter;
private DatabaseUtils.InsertHelper mGoodEventsInserter;
@Override
public void setUp() {
mBadDb = SQLiteDatabase.create(null);
assertNotNull(mBadDb);
mGoodDb = SQLiteDatabase.create(null);
assertNotNull(mGoodDb);
}
private void createVersion67EventsTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE Events (" +
"_id INTEGER PRIMARY KEY," +
"_sync_account TEXT," +
"_sync_account_type TEXT," +
"_sync_id TEXT," +
"_sync_version TEXT," +
"_sync_time TEXT," + // UTC
"_sync_local_id INTEGER," +
"_sync_dirty INTEGER," +
"_sync_mark INTEGER," + // To filter out new rows
"calendar_id INTEGER NOT NULL," +
"htmlUri TEXT," +
"title TEXT," +
"eventLocation TEXT," +
"description TEXT," +
"eventStatus INTEGER," +
"selfAttendeeStatus INTEGER NOT NULL DEFAULT 0," +
"commentsUri TEXT," +
"dtstart INTEGER," + // millis since epoch
"dtend INTEGER," + // millis since epoch
"eventTimezone TEXT," + // timezone for event
"duration TEXT," +
"allDay INTEGER NOT NULL DEFAULT 0," +
"visibility INTEGER NOT NULL DEFAULT 0," +
"transparency INTEGER NOT NULL DEFAULT 0," +
"hasAlarm INTEGER NOT NULL DEFAULT 0," +
"hasExtendedProperties INTEGER NOT NULL DEFAULT 0," +
"rrule TEXT," +
"rdate TEXT," +
"exrule TEXT," +
"exdate TEXT," +
"originalEvent TEXT," + // _sync_id of recurring event
"originalInstanceTime INTEGER," + // millis since epoch
"originalAllDay INTEGER," +
"lastDate INTEGER," + // millis since epoch
"hasAttendeeData INTEGER NOT NULL DEFAULT 0," +
"guestsCanModify INTEGER NOT NULL DEFAULT 0," +
"guestsCanInviteOthers INTEGER NOT NULL DEFAULT 1," +
"guestsCanSeeGuests INTEGER NOT NULL DEFAULT 1," +
"organizer STRING," +
"deleted INTEGER NOT NULL DEFAULT 0," +
"dtstart2 INTEGER," + //millis since epoch, allDay events in local timezone
"dtend2 INTEGER," + //millis since epoch, allDay events in local timezone
"eventTimezone2 TEXT," + //timezone for event with allDay events in local timezone
"syncAdapterData TEXT" + //available for use by sync adapters
");");
}
private void addVersion67Events() {
// April 5th 1:01:01 AM to April 6th 1:01:01
mBadDb.execSQL("INSERT INTO Events (_id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,allDay,calendar_id) " +
"VALUES (1,1270454471000,1270540872000,'P10S'," +
"1270454460000,1270540861000,'America/Los_Angeles','America/Los_Angeles',1,1);");
// April 5th midnight to April 6th midnight, duration cleared
mGoodDb.execSQL("INSERT INTO Events (_id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,allDay,calendar_id) " +
"VALUES (1,1270425600000,1270512000000,null," +
"1270450800000,1270537200000,'UTC','America/Los_Angeles',1,1);");
// April 5th 1:01:01 AM to April 6th 1:01:01, recurring weekly (We only check for the
// existence of an rrule so it doesn't matter if the day is correct)
mBadDb.execSQL("INSERT INTO Events (_id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,allDay,rrule,calendar_id) " +
"VALUES (2,1270454462000,1270540863000," +
"'P10S',1270454461000,1270540861000,'America/Los_Angeles','America/Los_Angeles',1," +
"'WEEKLY:MON',1);");
// April 5th midnight with 1 day duration, if only dtend was wrong we wouldn't fix it, but
// if anything else is wrong we clear dtend to be sure.
mGoodDb.execSQL("INSERT INTO Events (" +
"_id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,allDay,rrule,calendar_id)" +
"VALUES (2,1270425600000,null,'P1D',1270450800000,null," +
"'UTC','America/Los_Angeles',1," +
"'WEEKLY:MON',1);");
assertEquals(mBadDb.rawQuery("SELECT _id FROM Events;", null).getCount(), 2);
assertEquals(mGoodDb.rawQuery("SELECT _id FROM Events;", null).getCount(), 2);
}
@MediumTest
public void testUpgradeToVersion69() {
// Create event tables
createVersion67EventsTable(mBadDb);
createVersion67EventsTable(mGoodDb);
// Fill in good and bad events
addVersion67Events();
// Run the upgrade on the bad events
CalendarDatabaseHelper.upgradeToVersion69(mBadDb);
Cursor badCursor = null;
Cursor goodCursor = null;
try {
badCursor = mBadDb.rawQuery("SELECT _id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,rrule FROM Events WHERE allDay=?",
new String[] {"1"});
goodCursor = mGoodDb.rawQuery("SELECT _id,dtstart,dtend,duration,dtstart2,dtend2," +
"eventTimezone,eventTimezone2,rrule FROM Events WHERE allDay=?",
new String[] {"1"});
// Check that we get the correct results back
assertTrue(compareCursors(badCursor, goodCursor));
} finally {
if (badCursor != null) {
badCursor.close();
}
if (goodCursor != null) {
goodCursor.close();
}
}
}
/**
* Compares two cursors to see if they contain the same data.
*
* @return Returns true of the cursors contain the same data and are not null, false
* otherwise
*/
private static boolean compareCursors(Cursor c1, Cursor c2) {
if(c1 == null || c2 == null) {
Log.d("CDBT","c1 is " + c1 + " and c2 is " + c2);
return false;
}
int numColumns = c1.getColumnCount();
if (numColumns != c2.getColumnCount()) {
Log.d("CDBT","c1 has " + numColumns + " columns and c2 has " + c2.getColumnCount());
return false;
}
if (c1.getCount() != c2.getCount()) {
Log.d("CDBT","c1 has " + c1.getCount() + " rows and c2 has " + c2.getCount());
return false;
}
c1.moveToPosition(-1);
c2.moveToPosition(-1);
while(c1.moveToNext() && c2.moveToNext()) {
for(int i = 0; i < numColumns; i++) {
if(!TextUtils.equals(c1.getString(i),c2.getString(i))) {
Log.d("CDBT", c1.getString(i) + "\n" + c2.getString(i));
return false;
}
}
}
return true;
}
}