summaryrefslogtreecommitdiffstats
path: root/tests/src
diff options
context:
space:
mode:
authorErik <roboerik@android.com>2010-05-17 10:43:58 -0700
committerErik <roboerik@android.com>2010-05-21 14:28:43 -0700
commit73714169d34a55fc01e14b30897a1ebbacf9934e (patch)
tree845e22577ba48b57f764ff676d4030368a4f4e42 /tests/src
parenta54bd57246926e64233c7b25ee88754dfbdac99b (diff)
downloadandroid_packages_apps_Calendar-73714169d34a55fc01e14b30897a1ebbacf9934e.tar.gz
android_packages_apps_Calendar-73714169d34a55fc01e14b30897a1ebbacf9934e.tar.bz2
android_packages_apps_Calendar-73714169d34a55fc01e14b30897a1ebbacf9934e.zip
Creates a model for events and moves edit event methods into a helper
This is a step towards separating the UI and the logic for Calendar. This creates a standard model for representing events programatically. This model allows all the fields necessary for updating and managing an event in the db and a few early helper methods for working with them. EditEventHelper contains most of the logic from the previous EditEvent activity redone to use the new event model and without reliance on any UI elements and with db access minimized. It will still need to be modified to use a service for db access. Change-Id: Ic8f68269b75f43a0f2fd6408196176592d32e699
Diffstat (limited to 'tests/src')
-rw-r--r--tests/src/com/android/calendar/EditEventHelperTest.java1504
1 files changed, 1504 insertions, 0 deletions
diff --git a/tests/src/com/android/calendar/EditEventHelperTest.java b/tests/src/com/android/calendar/EditEventHelperTest.java
new file mode 100644
index 00000000..d2614395
--- /dev/null
+++ b/tests/src/com/android/calendar/EditEventHelperTest.java
@@ -0,0 +1,1504 @@
+/*
+ * 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.calendar;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+
+import android.content.ContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.Calendar.Attendees;
+import android.provider.Calendar.Events;
+import android.provider.Calendar.Reminders;
+import android.test.AndroidTestCase;
+import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
+import android.test.mock.MockResources;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.text.format.Time;
+import android.text.util.Rfc822Token;
+import android.util.Log;
+
+public class EditEventHelperTest extends AndroidTestCase {
+ private static final int TEST_EVENT_ID = 1;
+ private static final int TEST_EVENT_INDEX_ID = 0;
+ private static final long TEST_END = 1272931200000L;
+ private static final long TEST_END2 = 1272956400000L;
+ private static final long TEST_START = 1272844800000L;
+ private static final long TEST_START2 = 1272870000000L;
+
+ private static final int SAVE_EVENT_NEW_EVENT = 1;
+ private static final int SAVE_EVENT_MOD_RECUR = 2;
+ private static final int SAVE_EVENT_RECUR_TO_NORECUR = 3;
+ private static final int SAVE_EVENT_NORECUR_TO_RECUR= 4;
+ private static final int SAVE_EVENT_MOD_NORECUR = 5;
+ private static final int SAVE_EVENT_MOD_INSTANCE = 6;
+ private static final int SAVE_EVENT_ALLFOLLOW_TO_NORECUR = 7;
+ private static final int SAVE_EVENT_FIRST_TO_NORECUR = 8;
+ private static final int SAVE_EVENT_FIRST_TO_RECUR = 9;
+ private static final int SAVE_EVENT_ALLFOLLOW_TO_RECUR = 10;
+
+ private static String[] TEST_CURSOR_DATA = new String[] {
+ Integer.toString(TEST_EVENT_ID), // 0 _id
+ "The Question", // 1 title
+ "Evaluating Life, the Universe, and Everything",// 2 description
+ "Earth Mk2", // 3 location
+ "1", // 4 All Day
+ "0", // 5 Has alarm
+ "2", // 6 Calendar id
+ "1272844800000", // 7 dtstart, Monday, May 3rd midnight UTC
+ "1272931200000", // 8 dtend, Tuesday, May 4th midnight UTC
+ "P3652421990D", // 9 duration, (10 million years)
+ "UTC", // 10 event timezone
+ "FREQ=DAILY;WKST=SU", // 11 rrule
+ "unique per calendar stuff", // 12 sync id
+ "0", // 13 transparency
+ "3", // 14 visibility
+ "steve@gmail.com", // 15 owner account
+ "1", // 16 has attendee data
+ "America/Los_Angeles", // 17 event timezone 2
+ }; // These should match up with EditEventHelper.EVENT_PROJECTION
+
+ private static final String AUTHORITY_URI = "content://EditEventHelperAuthority/";
+ private static final String AUTHORITY = "EditEventHelperAuthority";
+
+ private static final String TEST_ADDRESSES =
+ "no good, ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+ private static final String TEST_ADDRESSES2 =
+ "no good, ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "different@email.bit";
+
+
+ private static final String TAG = "EEHTest";
+
+ private CalendarEventModel mModel1;
+ private CalendarEventModel mModel2;
+
+ private ContentValues mValues;
+ private ContentValues mExpectedValues;
+
+ private EditEventHelper mHelper;
+ private Context mContext;
+ private int mCurrentSaveTest = 0;
+
+ private Context buildTestContext() {
+ MockContext context = new MockContext() {
+ MockContentResolver mResolver;
+
+ @Override
+ public ContentResolver getContentResolver() {
+ if (mResolver == null) {
+ ContentProvider provider = new TestProvider();
+ mResolver = new MockContentResolver() {
+ @Override
+ public ContentProviderResult[] applyBatch(String authority,
+ ArrayList<ContentProviderOperation> operations) {
+ return mockApplyBatch(authority, operations);
+ }
+ };
+ mResolver.addProvider(AUTHORITY, provider);
+ }
+ return mResolver;
+ }
+
+ @Override
+ public Resources getResources() {
+ Resources res = new MockResources() {
+ @Override
+ // The actual selects singular vs plural as well and in the given language
+ public String getQuantityString(int id, int quantity) {
+ if (id == R.plurals.Nmins) {
+ return quantity + " mins";
+ }
+ if (id == R.plurals.Nminutes) {
+ return quantity + " minutes";
+ }
+ if (id == R.plurals.Nhours) {
+ return quantity + " hours";
+ }
+ if (id == R.plurals.Ndays) {
+ return quantity + " days";
+ }
+ return id + " " + quantity;
+ }
+ };
+ return res;
+ }
+ };
+ return context;
+ }
+
+ private ContentProviderResult[] mockApplyBatch(String authority,
+ ArrayList<ContentProviderOperation> operations) {
+ switch (mCurrentSaveTest) {
+ case SAVE_EVENT_NEW_EVENT:
+ // new recurring event
+ verifySaveEventNewEvent(operations);
+ break;
+ case SAVE_EVENT_MOD_RECUR:
+ // update to recurring event
+ verifySaveEventModifyRecurring(operations);
+ break;
+ case SAVE_EVENT_RECUR_TO_NORECUR:
+ // replace recurring event with non-recurring event
+ verifySaveEventRecurringToNonRecurring(operations);
+ break;
+ case SAVE_EVENT_NORECUR_TO_RECUR:
+ // update non-recurring event with recurring event
+ verifySaveEventNonRecurringToRecurring(operations);
+ break;
+ case SAVE_EVENT_MOD_NORECUR:
+ // update to non-recurring
+ verifySaveEventUpdateNonRecurring(operations);
+ break;
+ case SAVE_EVENT_MOD_INSTANCE:
+ // update to single instance of recurring event
+ verifySaveEventModifySingleInstance(operations);
+ break;
+ case SAVE_EVENT_ALLFOLLOW_TO_NORECUR:
+ // update all following with non-recurring event
+ verifySaveEventModifyAllFollowingWithNonRecurring(operations);
+ break;
+ case SAVE_EVENT_FIRST_TO_NORECUR:
+ // update all following with non-recurring event on first event in series
+ verifySaveEventModifyAllFollowingFirstWithNonRecurring(operations);
+ break;
+ case SAVE_EVENT_FIRST_TO_RECUR:
+ // update all following with recurring event on first event in series
+ verifySaveEventModifyAllFollowingFirstWithRecurring(operations);
+ break;
+ case SAVE_EVENT_ALLFOLLOW_TO_RECUR:
+ // update all following with recurring event on second event in series
+ verifySaveEventModifyAllFollowingWithRecurring(operations);
+ break;
+ }
+ return new ContentProviderResult[] {new ContentProviderResult(5)};
+ }
+
+ private void addOwnerAttendeeToOps(ArrayList<ContentProviderOperation> expectedOps, int id) {
+ addOwnerAttendee();
+ ContentProviderOperation.Builder b;
+ b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(mExpectedValues);
+ b.withValueBackReference(Reminders.EVENT_ID, id);
+ expectedOps.add(b.build());
+ }
+
+ // Some tests set the time values to one day later, this does that move in the values
+ private void moveExpectedTimeValuesForwardOneDay() {
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mExpectedValues.put(Events.DTSTART, TEST_START + dayInMs);
+ mExpectedValues.put(Events.DTSTART2, TEST_START2 + dayInMs);
+ mExpectedValues.put(Events.DTEND, TEST_END + dayInMs);
+ mExpectedValues.put(Events.DTEND2, TEST_END2 + dayInMs);
+ }
+
+ // Duplicates the delete and add for changing a single email address
+ private void addAttendeeChangesOps(ArrayList<ContentProviderOperation> expectedOps) {
+ ContentProviderOperation.Builder b =
+ ContentProviderOperation.newDelete(Attendees.CONTENT_URI);
+ b.withSelection(EditEventHelper.ATTENDEES_DELETE_PREFIX + "?)",
+ new String[] {"one.two.three@email.grue"});
+ expectedOps.add(b.build());
+
+ mExpectedValues.clear();
+ mExpectedValues.put(Attendees.ATTENDEE_NAME, (String)null);
+ mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "different@email.bit");
+ mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
+ mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
+ mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
+ mExpectedValues.put(Attendees.EVENT_ID, TEST_EVENT_ID);
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ expectedOps.add(b.build());
+ }
+
+ // This is a commonly added set of values
+ private void addOwnerAttendee() {
+ mExpectedValues.clear();
+ mExpectedValues.put(Attendees.ATTENDEE_EMAIL, mModel1.mOwnerAccount);
+ mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
+ mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
+ mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
+ }
+
+ /** Some tests add all the attendees to the db, the names and emails should match
+ * with {@link #TEST_ADDRESSES2} minus the 'no good'
+ */
+ private void addTestAttendees(ArrayList<ContentProviderOperation> ops,
+ boolean newEvent, int id) {
+ ContentProviderOperation.Builder b;
+ mExpectedValues.clear();
+ mExpectedValues.put(Attendees.ATTENDEE_NAME, (String)null);
+ mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "ad1@email.com");
+ mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
+ mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
+ mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
+
+ if (newEvent) {
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ b.withValueBackReference(Attendees.EVENT_ID, id);
+ } else {
+ mExpectedValues.put(Attendees.EVENT_ID, id);
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ }
+ ops.add(b.build());
+
+ mExpectedValues.clear();
+ mExpectedValues.put(Attendees.ATTENDEE_NAME, "First Last");
+ mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "first@email.com");
+ mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
+ mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
+ mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
+
+ if (newEvent) {
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ b.withValueBackReference(Attendees.EVENT_ID, id);
+ } else {
+ mExpectedValues.put(Attendees.EVENT_ID, id);
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ }
+ ops.add(b.build());
+
+ mExpectedValues.clear();
+ mExpectedValues.put(Attendees.ATTENDEE_NAME, (String)null);
+ mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "different@email.bit");
+ mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
+ mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
+ mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
+
+ if (newEvent) {
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ b.withValueBackReference(Attendees.EVENT_ID, id);
+ } else {
+ mExpectedValues.put(Attendees.EVENT_ID, id);
+ b = ContentProviderOperation
+ .newInsert(Attendees.CONTENT_URI)
+ .withValues(mExpectedValues);
+ }
+ ops.add(b.build());
+ }
+
+ @SmallTest
+ public void testSaveEventFailures() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+
+ // saveEvent should return false early if:
+ // -it was set to not ok
+ // -the model was null
+ // -the event doesn't represent the same event as the original event
+ // -there's a uri but an original event is not provided
+ mHelper.mEventOk = false;
+ assertFalse(mHelper.saveEvent(null, null, 0));
+ mHelper.mEventOk = true;
+ assertFalse(mHelper.saveEvent(null, null, 0));
+ mModel2.mId = 13;
+ assertFalse(mHelper.saveEvent(mModel1, mModel2, 0));
+ mModel2.mId = mModel1.mId;
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ mModel2.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ assertFalse(mHelper.saveEvent(mModel1, null, 0));
+ }
+
+ @SmallTest
+ public void testSaveEventNewEvent() {
+ // Creates a model of a new event for saving
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+ mCurrentSaveTest = SAVE_EVENT_NEW_EVENT;
+
+ assertTrue(mHelper.saveEvent(mModel1, null, 0));
+ }
+
+ private boolean verifySaveEventNewEvent(ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int br_id = 0;
+ mExpectedValues = buildTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ mExpectedValues.put(Events.HAS_ATTENDEE_DATA, 1);
+ ContentProviderOperation.Builder b = ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues);
+ expectedOps.add(b.build());
+
+ // This call has a separate unit test so we'll use it to simplify making the expected vals
+ mHelper.saveRemindersWithBackRef(expectedOps, br_id, mModel1.mReminderMinutes,
+ new ArrayList<Integer>(), true);
+
+ addOwnerAttendeeToOps(expectedOps, br_id);
+
+ addTestAttendees(expectedOps, true, br_id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifyRecurring() {
+ // Creates an original and an updated recurring event model
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ // Updating a recurring event with a new attendee list
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+ mCurrentSaveTest = SAVE_EVENT_MOD_RECUR;
+
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
+ }
+
+ private boolean verifySaveEventModifyRecurring(ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int br_id = 0;
+ mExpectedValues = buildTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ // This is tested elsewhere, used for convenience here
+ mHelper.checkTimeDependentFields(mModel2, mModel1, mExpectedValues,
+ EditEventHelper.MODIFY_ALL);
+
+ expectedOps.add(
+ ContentProviderOperation
+ .newUpdate(mModel1.mUri)
+ .withValues(mExpectedValues)
+ .build());
+
+ // This call has a separate unit test so we'll use it to simplify making the expected vals
+ mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, false);
+
+ addAttendeeChangesOps(expectedOps);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventRecurringToNonRecurring() {
+ // Creates an original and an updated recurring event model
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ // Updating a recurring event with a new attendee list
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Replace an existing recurring event with a non-recurring event
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2;
+ mCurrentSaveTest = SAVE_EVENT_RECUR_TO_NORECUR;
+
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
+ }
+
+ private boolean verifySaveEventRecurringToNonRecurring(ArrayList<ContentProviderOperation> ops)
+ {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int id = 0;
+ mExpectedValues = buildNonRecurringTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ // This is tested elsewhere, used for convenience here
+ mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
+ EditEventHelper.MODIFY_ALL);
+
+ expectedOps.add(ContentProviderOperation.newDelete(mModel1.mUri).build());
+ id = expectedOps.size();
+ expectedOps.add(ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues)
+ .build());
+
+ mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addOwnerAttendeeToOps(expectedOps, id);
+
+ addTestAttendees(expectedOps, true, id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventNonRecurringToRecurring() {
+ // Creates an original non-recurring and an updated recurring event model
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ // Updating a recurring event with a new attendee list
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ mModel2.mRrule = null;
+ mModel2.mEnd = TEST_END2;
+ mCurrentSaveTest = SAVE_EVENT_NORECUR_TO_RECUR;
+
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
+ }
+
+ private boolean verifySaveEventNonRecurringToRecurring(ArrayList<ContentProviderOperation> ops)
+ {
+ // Changing a non-recurring event to a recurring event should generate the same operations
+ // as just modifying a recurring event.
+ return verifySaveEventModifyRecurring(ops);
+ }
+
+ @SmallTest
+ public void testSaveEventUpdateNonRecurring() {
+ // Creates an original non-recurring and an updated recurring event model
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ // Updating a recurring event with a new attendee list
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ mModel2.mRrule = null;
+ mModel2.mEnd = TEST_END2;
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2;
+ mCurrentSaveTest = SAVE_EVENT_MOD_NORECUR;
+
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
+ }
+
+ private boolean verifySaveEventUpdateNonRecurring(ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int id = TEST_EVENT_ID;
+ mExpectedValues = buildNonRecurringTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ // This is tested elsewhere, used for convenience here
+ mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
+ EditEventHelper.MODIFY_ALL);
+ expectedOps.add(
+ ContentProviderOperation
+ .newUpdate(mModel1.mUri)
+ .withValues(mExpectedValues)
+ .build());
+ // This call has a separate unit test so we'll use it to simplify making the expected vals
+ mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, false);
+ addAttendeeChangesOps(expectedOps);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifySingleInstance() {
+ // Creates an original non-recurring and an updated recurring event model
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Modify the second instance of the event
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2 + dayInMs;
+ mModel1.mStart += dayInMs;
+ mModel1.mOriginalStart = mModel1.mStart;
+
+ mCurrentSaveTest = SAVE_EVENT_MOD_INSTANCE;
+ // Only modify this instance
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_SELECTED));
+ }
+
+ private boolean verifySaveEventModifySingleInstance(ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int id = 0;
+ mExpectedValues = buildNonRecurringTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ // This is tested elsewhere, used for convenience here
+ mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
+ EditEventHelper.MODIFY_ALL);
+
+ moveExpectedTimeValuesForwardOneDay();
+ mExpectedValues.put(Events.ORIGINAL_EVENT, mModel2.mSyncId);
+ mExpectedValues.put(Events.ORIGINAL_INSTANCE_TIME, mModel1.mOriginalStart);
+ mExpectedValues.put(Events.ORIGINAL_ALL_DAY, 1);
+
+ ContentProviderOperation.Builder b = ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues);
+ expectedOps.add(b.build());
+
+ mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addOwnerAttendeeToOps(expectedOps, id);
+
+ addTestAttendees(expectedOps, true, id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifyAllFollowingWithNonRecurring() {
+ // Creates an original and an updated recurring event model. The update starts on the 2nd
+ // instance of the original.
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ mModel2.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Modify the second instance of the event
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2 + dayInMs;
+ mModel1.mStart += dayInMs;
+ mModel1.mOriginalStart = mModel1.mStart;
+
+ mCurrentSaveTest = SAVE_EVENT_ALLFOLLOW_TO_NORECUR;
+ // Only modify this instance
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
+ }
+
+ private boolean verifySaveEventModifyAllFollowingWithNonRecurring(
+ ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int id = 0;
+ mExpectedValues = buildNonRecurringTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ moveExpectedTimeValuesForwardOneDay();
+ // This has a separate test
+ mHelper.updatePastEvents(expectedOps, mModel2, mModel1.mOriginalStart);
+ id = expectedOps.size();
+ expectedOps.add(ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues)
+ .build());
+
+ mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addOwnerAttendeeToOps(expectedOps, id);
+
+ addTestAttendees(expectedOps, true, id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifyAllFollowingFirstWithNonRecurring() {
+ // Creates an original recurring and an updated non-recurring event model for the first
+ // instance. This should replace the original event with a non-recurring event.
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Move the event one day but keep original start set to the first instance
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2 + dayInMs;
+ mModel1.mStart += dayInMs;
+
+ mCurrentSaveTest = SAVE_EVENT_FIRST_TO_NORECUR;
+ // Only modify this instance
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
+ }
+
+ private boolean verifySaveEventModifyAllFollowingFirstWithNonRecurring(
+ ArrayList<ContentProviderOperation> ops) {
+
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int id = 0;
+ mExpectedValues = buildNonRecurringTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ moveExpectedTimeValuesForwardOneDay();
+
+ expectedOps.add(ContentProviderOperation.newDelete(mModel1.mUri).build());
+ id = expectedOps.size();
+ expectedOps.add(ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues)
+ .build());
+
+ mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addOwnerAttendeeToOps(expectedOps, id);
+
+ addTestAttendees(expectedOps, true, id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifyAllFollowingFirstWithRecurring() {
+ // Creates an original recurring and an updated recurring event model for the first instance
+ // This should replace the original event with a new recurrence
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ // And a new start time to ensure the time fields aren't removed
+ mModel1.mOriginalStart = TEST_START2;
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Move the event one day but keep original start set to the first instance
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mModel1.mStart += dayInMs;
+
+ mCurrentSaveTest = SAVE_EVENT_FIRST_TO_RECUR;
+ // Only modify this instance
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
+ }
+
+ private boolean verifySaveEventModifyAllFollowingFirstWithRecurring(
+ ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int br_id = 0;
+ mExpectedValues = buildTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ moveExpectedTimeValuesForwardOneDay();
+ mExpectedValues.put(Events.DTEND, (Long)null);
+ mExpectedValues.put(Events.DTEND2, (Long)null);
+ // This is tested elsewhere, used for convenience here
+ mHelper.checkTimeDependentFields(mModel2, mModel1, mExpectedValues,
+ EditEventHelper.MODIFY_ALL_FOLLOWING);
+
+ expectedOps.add(
+ ContentProviderOperation
+ .newUpdate(mModel1.mUri)
+ .withValues(mExpectedValues)
+ .build());
+
+ // This call has a separate unit test so we'll use it to simplify making the expected vals
+ mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addAttendeeChangesOps(expectedOps);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testSaveEventModifyAllFollowingWithRecurring() {
+ // Creates an original recurring and an updated recurring event model
+ // for the second instance. This should end the original recurrence and add a new
+ // recurrence.
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel1.mAttendees = TEST_ADDRESSES2;
+
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ mModel2.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+
+ // The original model is assumed correct so drop the no good bit
+ mModel2.mAttendees = "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
+ "one.two.three@email.grue";
+
+ // Move the event one day and the original start so it references the second instance
+ long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
+ mModel1.mStart += dayInMs;
+ mModel1.mOriginalStart = mModel1.mStart;
+
+ mCurrentSaveTest = SAVE_EVENT_ALLFOLLOW_TO_RECUR;
+ // Only modify this instance
+ assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
+ }
+
+ private boolean verifySaveEventModifyAllFollowingWithRecurring(
+ ArrayList<ContentProviderOperation> ops) {
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ int br_id = 0;
+ mExpectedValues = buildTestValues();
+ mExpectedValues.put(Events.HAS_ALARM, 0);
+ moveExpectedTimeValuesForwardOneDay();
+ mExpectedValues.put(Events.DTEND, (Long)null);
+ mExpectedValues.put(Events.DTEND2, (Long)null);
+ // This is tested elsewhere, used for convenience here
+ mHelper.updatePastEvents(expectedOps, mModel2, mModel1.mOriginalStart);
+
+ br_id = expectedOps.size();
+ expectedOps.add(ContentProviderOperation
+ .newInsert(Events.CONTENT_URI)
+ .withValues(mExpectedValues)
+ .build());
+
+ // This call has a separate unit test so we'll use it to simplify making the expected vals
+ mHelper.saveRemindersWithBackRef(expectedOps, br_id, mModel1.mReminderMinutes,
+ mModel2.mReminderMinutes, true);
+
+ addOwnerAttendeeToOps(expectedOps, br_id);
+
+ addTestAttendees(expectedOps, true, br_id);
+
+ assertEquals(ops, expectedOps);
+ return true;
+ }
+
+ @SmallTest
+ public void testGetAddressesFromList() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ LinkedHashSet<Rfc822Token> expected = new LinkedHashSet<Rfc822Token>();
+ expected.add(new Rfc822Token(null, "ad1@email.com", ""));
+ expected.add(new Rfc822Token("First Last", "first@email.com", "comment"));
+ expected.add(new Rfc822Token(null, "one.two.three@email.grue", ""));
+
+ LinkedHashSet<Rfc822Token> actual = mHelper.getAddressesFromList(TEST_ADDRESSES);
+ assertEquals(actual, expected);
+ }
+
+ @SmallTest
+ public void testCheckTimeDependentFieldsNoChanges() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel2.mRrule = null;
+
+ mValues = buildTestValues();
+ mExpectedValues = buildTestValues();
+
+ // if any time/recurrence vals are different but there's no new rrule it
+ // shouldn't change
+ mHelper.checkTimeDependentFields(mModel1, mModel2, mValues, EditEventHelper.MODIFY_ALL);
+ assertEquals(mValues, mExpectedValues);
+
+ // also, if vals are different and it's not modifying all it shouldn't
+ // change.
+ mModel2.mRrule = "something else";
+ mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
+ EditEventHelper.MODIFY_SELECTED);
+ assertEquals(mValues, mExpectedValues);
+
+ // if vals changed and modify all is selected dtstart should be updated
+ // by the difference
+ // between originalStart and start
+ mModel2.mOriginalStart = mModel2.mStart + 60000; // set the old time to
+ // one minute later
+ mModel2.mStart += 120000; // move the event another 1 minute.
+
+ // shouldn't change for an allday event
+ // expectedVals.put(Events.DTSTART, mModel1.mStart + 60000); // should
+ // now be 1 minute later
+ // dtstart2 shouldn't change since it gets rezeroed in the local
+ // timezone for allDay events
+
+ mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
+ EditEventHelper.MODIFY_SELECTED);
+ assertEquals(mValues, mExpectedValues);
+ }
+
+ @SmallTest
+ public void testCheckTimeDependentFieldsChanges() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mModel1 = buildTestModel();
+ mModel2 = buildTestModel();
+ mModel2.mRrule = null;
+
+ mValues = buildTestValues();
+ mExpectedValues = buildTestValues();
+
+ // if all the time values are the same it should remove them from vals
+ mModel2.mRrule = mModel1.mRrule;
+ mModel2.mStart = mModel1.mStart;
+ mModel2.mOriginalStart = mModel2.mStart;
+
+ mExpectedValues.remove(Events.DTSTART);
+ mExpectedValues.remove(Events.DTSTART2);
+ mExpectedValues.remove(Events.DTEND);
+ mExpectedValues.remove(Events.DTEND2);
+ mExpectedValues.remove(Events.DURATION);
+ mExpectedValues.remove(Events.ALL_DAY);
+ mExpectedValues.remove(Events.RRULE);
+ mExpectedValues.remove(Events.EVENT_TIMEZONE);
+ mExpectedValues.remove(Events.EVENT_TIMEZONE2);
+
+ mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
+ EditEventHelper.MODIFY_SELECTED);
+ assertEquals(mValues, mExpectedValues);
+
+ }
+
+ @SmallTest
+ public void testUpdatePastEvents() {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ long initialBeginTime = 1472864400000L; // Sep 3, 2016, 1AM
+ mValues = new ContentValues();
+
+ mModel1 = buildTestModel();
+ mModel1.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ mValues.put(Events.RRULE, "FREQ=DAILY;UNTIL=20160903;WKST=SU"); // yyyymmddThhmmssZ
+
+ ContentProviderOperation.Builder b =
+ ContentProviderOperation.newUpdate(mModel1.mUri).withValues(mValues);
+ expectedOps.add(b.build());
+
+ mHelper.updatePastEvents(ops, mModel1, initialBeginTime);
+ assertEquals(ops, expectedOps);
+
+ mModel1.mAllDay = false;
+
+ mValues.put(Events.RRULE, "FREQ=DAILY;UNTIL=20160903T005959Z;WKST=SU"); // yyyymmddThhmmssZ
+
+ expectedOps.clear();
+ b = ContentProviderOperation.newUpdate(mModel1.mUri).withValues(mValues);
+ expectedOps.add(b.build());
+
+ ops.clear();
+ mHelper.updatePastEvents(ops, mModel1, initialBeginTime);
+ assertEquals(ops, expectedOps);
+ }
+
+ @SmallTest
+ public void testConstructReminderLabel() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+
+ String label = mHelper.constructReminderLabel(35, true);
+ assertEquals(label, "35 mins");
+
+ label = mHelper.constructReminderLabel(72, false);
+ assertEquals(label, "72 minutes");
+
+ label = mHelper.constructReminderLabel(60, true);
+ assertEquals(label, "1 hours");
+
+ label = mHelper.constructReminderLabel(60 * 48, true);
+ assertEquals(label, "2 days");
+ }
+
+ @SmallTest
+ public void testIsSameEvent() {
+ mModel1 = new CalendarEventModel();
+ mModel2 = new CalendarEventModel();
+
+ mModel1.mId = 1;
+ mModel1.mCalendarId = 1;
+ mModel2.mId = 1;
+ mModel2.mCalendarId = 1;
+
+ // considered the same if the event and calendar ids both match
+ assertTrue(EditEventHelper.isSameEvent(mModel1, mModel2));
+
+ mModel2.mId = 2;
+ assertFalse(EditEventHelper.isSameEvent(mModel1, mModel2));
+
+ mModel2.mId = 1;
+ mModel2.mCalendarId = 2;
+ assertFalse(EditEventHelper.isSameEvent(mModel1, mModel2));
+ }
+
+ @SmallTest
+ public void testSaveReminders() {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ long eventId = TEST_EVENT_ID;
+ ArrayList<Integer> reminderMinutes = new ArrayList<Integer>();
+ ArrayList<Integer> originalMinutes = new ArrayList<Integer>();
+ boolean forceSave = true;
+ boolean result;
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+ assertNotNull(mHelper);
+
+ // First test forcing a delete with no reminders.
+ String where = Reminders.EVENT_ID + "=?";
+ String[] args = new String[] {Long.toString(eventId)};
+ ContentProviderOperation.Builder b =
+ ContentProviderOperation.newDelete(Reminders.CONTENT_URI);
+ b.withSelection(where, args);
+ expectedOps.add(b.build());
+
+ result = mHelper.saveReminders(ops, eventId, reminderMinutes, originalMinutes, forceSave);
+ assertTrue(result);
+ assertEquals(ops, expectedOps);
+
+ // Now test calling save with identical reminders and no forcing
+ reminderMinutes.add(5);
+ reminderMinutes.add(10);
+ reminderMinutes.add(15);
+
+ originalMinutes.add(5);
+ originalMinutes.add(10);
+ originalMinutes.add(15);
+
+ forceSave = false;
+
+ ops.clear();
+
+ // Should fail to create any ops since nothing changed
+ result = mHelper.saveReminders(ops, eventId, reminderMinutes, originalMinutes, forceSave);
+ assertFalse(result);
+ assertEquals(ops.size(), 0);
+
+ //Now test adding a single reminder
+ originalMinutes.remove(2);
+
+ addExpectedMinutes(expectedOps);
+
+ result = mHelper.saveReminders(ops, eventId, reminderMinutes, originalMinutes, forceSave);
+ assertTrue(result);
+ assertEquals(ops, expectedOps);
+ }
+
+ @SmallTest
+ public void testSaveRemindersWithBackRef() {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
+ long eventId = TEST_EVENT_ID;
+ ArrayList<Integer> reminderMinutes = new ArrayList<Integer>();
+ ArrayList<Integer> originalMinutes = new ArrayList<Integer>();
+ boolean forceSave = true;
+ boolean result;
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+ assertNotNull(mHelper);
+
+ // First test forcing a delete with no reminders.
+ ContentProviderOperation.Builder b =
+ ContentProviderOperation.newDelete(Reminders.CONTENT_URI);
+ b.withSelection(Reminders.EVENT_ID + "=?", new String[1]);
+ b.withSelectionBackReference(0, TEST_EVENT_INDEX_ID);
+ expectedOps.add(b.build());
+
+ result =
+ mHelper.saveRemindersWithBackRef(ops, TEST_EVENT_INDEX_ID, reminderMinutes,
+ originalMinutes, forceSave);
+ assertTrue(result);
+ assertEquals(ops, expectedOps);
+
+ // Now test calling save with identical reminders and no forcing
+ reminderMinutes.add(5);
+ reminderMinutes.add(10);
+ reminderMinutes.add(15);
+
+ originalMinutes.add(5);
+ originalMinutes.add(10);
+ originalMinutes.add(15);
+
+ forceSave = false;
+
+ ops.clear();
+
+ result = mHelper.saveRemindersWithBackRef(ops, ops.size(), reminderMinutes, originalMinutes,
+ forceSave);
+ assertFalse(result);
+ assertEquals(ops.size(), 0);
+
+ //Now test adding a single reminder
+ originalMinutes.remove(2);
+
+ addExpectedMinutesWithBackRef(expectedOps);
+
+ result = mHelper.saveRemindersWithBackRef(ops, ops.size(), reminderMinutes, originalMinutes,
+ forceSave);
+ assertTrue(result);
+ assertEquals(ops, expectedOps);
+ }
+
+ @SmallTest
+ public void testIsFirstEventInSeries() {
+ mModel1 = new CalendarEventModel();
+ mModel2 = new CalendarEventModel();
+
+ // It's considered the first event if the original start of the new model matches the
+ // start of the old model
+ mModel1.mOriginalStart = 100;
+ mModel1.mStart = 200;
+ mModel2.mOriginalStart = 100;
+ mModel2.mStart = 100;
+
+ assertTrue(EditEventHelper.isFirstEventInSeries(mModel1, mModel2));
+
+ mModel1.mOriginalStart = 80;
+ assertFalse(EditEventHelper.isFirstEventInSeries(mModel1, mModel2));
+ }
+
+ @SmallTest
+ public void testAddRecurrenceRule() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+ mValues = new ContentValues();
+ mExpectedValues = new ContentValues();
+ mModel1 = new CalendarEventModel();
+
+ mExpectedValues.put(Events.RRULE, "Weekly, Monday");
+ mExpectedValues.put(Events.DURATION, "P60S");
+ mExpectedValues.put(Events.DTEND, (Long) null);
+ mExpectedValues.put(Events.DTEND2, (Long) null);
+
+ mModel1.mRrule = "Weekly, Monday";
+ mModel1.mStart = 1;
+ mModel1.mEnd = 60001;
+ mModel1.mAllDay = false;
+
+ mHelper.addRecurrenceRule(mValues, mModel1);
+ assertEquals(mValues, mExpectedValues);
+
+ mExpectedValues.put(Events.DURATION, "P1D");
+
+ mModel1.mAllDay = true;
+ mValues.clear();
+
+ mHelper.addRecurrenceRule(mValues, mModel1);
+ assertEquals(mValues, mExpectedValues);
+
+ }
+
+ @SmallTest
+ public void testUpdateRecurrenceRule() {
+ int selection = EditEventHelper.DOES_NOT_REPEAT;
+ mModel1 = new CalendarEventModel();
+ mModel1.mTimezone = Time.TIMEZONE_UTC;
+ mModel1.mStart = 1272665741000L; // Fri, April 30th ~ 3:17PM
+
+ mModel1.mRrule = "This should go away";
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertNull(mModel1.mRrule);
+
+ mModel1.mRrule = "This shouldn't change";
+ selection = EditEventHelper.REPEATS_CUSTOM;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "This shouldn't change");
+
+ selection = EditEventHelper.REPEATS_DAILY;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=DAILY;WKST=SU");
+
+ selection = EditEventHelper.REPEATS_EVERY_WEEKDAY;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=WEEKLY;WKST=SU;BYDAY=MO,TU,WE,TH,FR");
+
+ selection = EditEventHelper.REPEATS_WEEKLY_ON_DAY;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=WEEKLY;WKST=SU;BYDAY=FR");
+
+ selection = EditEventHelper.REPEATS_MONTHLY_ON_DAY;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=30");
+
+ selection = EditEventHelper.REPEATS_MONTHLY_ON_DAY_COUNT;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=MONTHLY;WKST=SU;BYDAY=-1FR");
+
+ selection = EditEventHelper.REPEATS_YEARLY;
+
+ EditEventHelper.updateRecurrenceRule(selection, mModel1);
+ assertEquals(mModel1.mRrule, "FREQ=YEARLY;WKST=SU");
+ }
+
+ @SmallTest
+ public void testSetModelFromCursor() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+ MatrixCursor c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
+ c.addRow(TEST_CURSOR_DATA);
+
+ mModel1 = new CalendarEventModel();
+ mModel2 = buildTestModel();
+
+ mHelper.setModelFromCursor(mModel1, c);
+ assertEquals(mModel1, mModel2);
+
+ TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_ALL_DAY] = "0";
+ c.close();
+ c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
+ c.addRow(TEST_CURSOR_DATA);
+
+ mModel2.mAllDay = false;
+ mModel2.mStart = TEST_START; // UTC time, non-allday events don't
+ // have special tz rules
+ mModel2.mTimezone = "UTC";
+
+ mHelper.setModelFromCursor(mModel1, c);
+ assertEquals(mModel1, mModel2);
+
+ TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_RRULE] = null;
+ c.close();
+ c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
+ c.addRow(TEST_CURSOR_DATA);
+
+ mModel2.mRrule = null;
+ mModel2.mEnd = TEST_END;
+ mModel2.mDuration = null;
+
+ mHelper.setModelFromCursor(mModel1, c);
+ assertEquals(mModel1, mModel2);
+
+ TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_ALL_DAY] = "1";
+ c.close();
+ c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
+ c.addRow(TEST_CURSOR_DATA);
+
+ mModel2.mAllDay = true;
+ mModel2.mStart = TEST_START2; // Monday, May 3rd, midnight America/LA
+ // time
+ mModel2.mEnd = TEST_END2; // Tuesday, May 4th, midnight America/LA
+ // time
+ mModel2.mTimezone = "America/Los_Angeles";
+
+ mHelper.setModelFromCursor(mModel1, c);
+ assertEquals(mModel1, mModel2);
+ }
+
+ @SmallTest
+ public void testGetContentValuesFromModel() {
+ mContext = buildTestContext();
+ mHelper = new EditEventHelper(mContext, null);
+ mExpectedValues = buildTestValues();
+ mModel1 = buildTestModel();
+
+ ContentValues values = mHelper.getContentValuesFromModel(mModel1);
+ assertEquals(values, mExpectedValues);
+
+ mModel1.mRrule = null;
+ mModel1.mEnd = TEST_END2; // LA time
+
+ mExpectedValues.put(Events.RRULE, (String) null);
+ mExpectedValues.put(Events.DURATION, (String) null);
+ mExpectedValues.put(Events.DTEND, TEST_END); // UTC time
+ mExpectedValues.put(Events.DTEND2, TEST_END2); // LA time
+
+ values = mHelper.getContentValuesFromModel(mModel1);
+ assertEquals(values, mExpectedValues);
+
+ mModel1.mAllDay = false;
+
+ mExpectedValues.put(Events.ALL_DAY, 0);
+ mExpectedValues.put(Events.DTSTART, TEST_START2); // LA time
+ mExpectedValues.put(Events.DTEND, TEST_END2); // LA time
+ // not an allday event so timezone isn't modified
+ mExpectedValues.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
+
+ values = mHelper.getContentValuesFromModel(mModel1);
+ assertEquals(values, mExpectedValues);
+ }
+
+ @SmallTest
+ public void testExtractDomain() {
+ String domain = EditEventHelper.extractDomain("test.email@gmail.com");
+ assertEquals(domain, "gmail.com");
+
+ domain = EditEventHelper.extractDomain("bademail.no#$%at symbol");
+ assertNull(domain);
+ }
+
+ private void addExpectedMinutes(ArrayList<ContentProviderOperation> expectedOps) {
+ ContentProviderOperation.Builder b;
+ mValues = new ContentValues();
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 5);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ expectedOps.add(b.build());
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 10);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ expectedOps.add(b.build());
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 15);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ expectedOps.add(b.build());
+ }
+
+ private void addExpectedMinutesWithBackRef(ArrayList<ContentProviderOperation> expectedOps) {
+ ContentProviderOperation.Builder b;
+ mValues = new ContentValues();
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 5);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
+ expectedOps.add(b.build());
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 10);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
+ expectedOps.add(b.build());
+
+ mValues.clear();
+ mValues.put(Reminders.MINUTES, 15);
+ mValues.put(Reminders.METHOD, Reminders.METHOD_ALERT);
+ b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
+ b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
+ expectedOps.add(b.build());
+ }
+
+ private static void assertEquals(ArrayList<ContentProviderOperation> expected,
+ ArrayList<ContentProviderOperation> actual) {
+ if (expected == null) {
+ assertNull(actual);
+ }
+ int size = expected.size();
+
+ assertEquals(size, actual.size());
+
+ for (int i = 0; i < size; i++) {
+ assertTrue(cpoEquals(expected.get(i), actual.get(i)));
+ }
+
+ }
+
+ private static boolean cpoEquals(ContentProviderOperation cpo1, ContentProviderOperation cpo2) {
+ if (cpo1 == null && cpo2 != null) {
+ return false;
+ }
+ if (cpo1 == cpo2) {
+ return true;
+ }
+ if (cpo2 == null) {
+ return false;
+ }
+
+ return TextUtils.equals(cpo1.toString(), cpo2.toString());
+ }
+
+ // Generates a default model for testing. Should match up with
+ // generateTestValues
+ private CalendarEventModel buildTestModel() {
+ CalendarEventModel model = new CalendarEventModel();
+ model.mId = TEST_EVENT_ID;
+ model.mTitle = "The Question";
+ model.mDescription = "Evaluating Life, the Universe, and Everything";
+ model.mLocation = "Earth Mk2";
+ model.mAllDay = true;
+ model.mHasAlarm = false;
+ model.mCalendarId = 2;
+ model.mStart = TEST_START2; // Monday, May 3rd, midnight America/LA
+ // time
+ model.mDuration = "P3652421990D";
+ model.mTimezone = "America/Los_Angeles"; // The model uses the same
+ // timezone for allday
+ model.mRrule = "FREQ=DAILY;WKST=SU";
+ model.mSyncId = "unique per calendar stuff";
+ model.mTransparency = false;
+ model.mVisibility = 2; // This is one less than the values written if >0
+ model.mOwnerAccount = "steve@gmail.com";
+ model.mHasAttendeeData = true;
+ model.mTimezone2 = "America/Los_Angeles";
+ // model.mUri = Uri.parse(AUTHORITY_URI + TEST_EVENT_ID);
+
+ return model;
+ }
+
+ // Generates a default set of values for testing. Should match up with
+ // generateTestModel
+ private ContentValues buildTestValues() {
+ ContentValues values = new ContentValues();
+
+ values.put(Events.CALENDAR_ID, 2L);
+ values.put(Events.EVENT_TIMEZONE, "UTC"); // Allday events are converted
+ // to UTC for the db
+ values.put(Events.EVENT_TIMEZONE2, "America/Los_Angeles");
+ values.put(Events.TITLE, "The Question");
+ values.put(Events.ALL_DAY, 1);
+ values.put(Events.DTSTART, TEST_START); // Monday, May 3rd, midnight
+ // UTC time
+ values.put(Events.DTSTART2, TEST_START2); // Monday, May 3rd,
+ // midnight America/LA time
+ values.put(Events.RRULE, "FREQ=DAILY;WKST=SU");
+ values.put(Events.DURATION, "P3652421990D");
+ values.put(Events.DTEND, (Long) null);
+ values.put(Events.DTEND2, (Long) null);
+ values.put(Events.DESCRIPTION, "Evaluating Life, the Universe, and Everything");
+ values.put(Events.EVENT_LOCATION, "Earth Mk2");
+ values.put(Events.TRANSPARENCY, 0);
+ values.put(Events.VISIBILITY, 3); // This is one more than the model if
+ // >0
+
+ return values;
+ }
+
+ private ContentValues buildNonRecurringTestValues() {
+ ContentValues values = buildTestValues();
+ values.put(Events.DURATION, (String)null);
+ values.put(Events.DTEND, TEST_END);
+ values.put(Events.DTEND2, TEST_END2);
+ values.put(Events.RRULE, (String)null);
+ return values;
+ }
+
+ // This gets called by EditEventHelper to read or write the data
+ class TestProvider extends ContentProvider {
+ int index = 0;
+
+ public TestProvider() {
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String orderBy) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+ }
+
+}