diff --git a/app/build.gradle b/app/build.gradle index 76dec230..3c243b05 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,10 +60,7 @@ dependencies { // dnsjava for querying SRV/TXT records compile 'dnsjava:dnsjava:2.1.6' // HttpClient 4.3, Android flavour for WebDAV operations - // we have to use our own patched build of 4.3.5.2-SNAPSHOT to avoid - // https://issues.apache.org/jira/browse/HTTPCLIENT-1591 - compile files('lib/httpclient-android-4.3.5.2-davdroid1.jar') - // compile 'org.apache.httpcomponents:httpclient-android:4.3.5.2-SNAPSHOT' + compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1' // SimpleXML for parsing and generating WebDAV messages compile('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' diff --git a/app/lib/httpclient-android-4.3.5.2-davdroid1.jar b/app/lib/httpclient-android-4.3.5.2-davdroid1.jar deleted file mode 100644 index 1586e9cc..00000000 Binary files a/app/lib/httpclient-android-4.3.5.2-davdroid1.jar and /dev/null differ diff --git a/app/src/androidTest/assets/recurring-with-exception1.ics b/app/src/androidTest/assets/recurring-with-exception1.ics new file mode 100644 index 00000000..0382497e --- /dev/null +++ b/app/src/androidTest/assets/recurring-with-exception1.ics @@ -0,0 +1,17 @@ +BEGIN:VCALENDAR +VERSION:2.0 +BEGIN:VEVENT +UID:fcb42e4d-bc6e-4499-97f0-6616a02da7bc +SUMMARY:Recurring event with one exception +RRULE:FREQ=DAILY;COUNT=5 +DTSTART;VALUE=DATE:20150501 +DTEND;VALUE=DATE:20150502 +END:VEVENT +BEGIN:VEVENT +UID:fcb42e4d-bc6e-4499-97f0-6616a02da7bc +RECURRENCE-ID;VALUE=DATE:20150503 +DTSTART;VALUE=DATE:20150503 +DTEND;VALUE=DATE:20150504 +SUMMARY:Another summary for the third day +END:VEVENT +END:VCALENDAR \ No newline at end of file diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/EventTest.java b/app/src/androidTest/java/at/bitfire/davdroid/resource/EventTest.java index d1665df3..67aeeeba 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/resource/EventTest.java +++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/EventTest.java @@ -30,10 +30,18 @@ public class EventTest extends InstrumentationTestCase { eAllDay1Day = parseCalendar("all-day-1day.ics"); eAllDay10Days = parseCalendar("all-day-10days.ics"); eAllDay0Sec = parseCalendar("all-day-0sec.ics"); - - //assertEquals("Test-Ereignis im schönen Wien", e.getSummary()); } - + + + public void testRecurringWithException() throws Exception { + Event event = parseCalendar("recurring-with-exception1.ics"); + assertTrue(event.isAllDay()); + + assertEquals(1, event.getExceptions().size()); + Event exception = event.getExceptions().get(0); + assertEquals("20150503", exception.getRecurrenceId().getValue()); + assertEquals("Another summary for the third day", exception.getSummary()); + } public void testStartEndTimes() throws IOException, ParserException, InvalidResourceException { // event with start+end date-time diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.java b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.java index 81c56656..050505a6 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.java +++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.java @@ -10,12 +10,16 @@ package at.bitfire.davdroid.resource; import java.util.Calendar; import lombok.Cleanup; + +import android.Manifest; import android.accounts.Account; import android.annotation.TargetApi; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Build; @@ -26,6 +30,8 @@ import android.provider.CalendarContract.Calendars; import android.provider.CalendarContract.Events; import android.provider.CalendarContract.Reminders; import android.test.InstrumentationTestCase; +import android.test.IsolatedContext; +import android.test.mock.MockContentResolver; import android.util.Log; import at.bitfire.davdroid.resource.LocalCalendar; import at.bitfire.davdroid.resource.LocalStorageException; @@ -33,20 +39,23 @@ import at.bitfire.davdroid.resource.LocalStorageException; public class LocalCalendarTest extends InstrumentationTestCase { private static final String - TAG = "davroid.test", + TAG = "davdroid.test", + accountName = "at.bitfire.davdroid.test", calendarName = "DAVdroid_Test"; - + + Context targetContext; + ContentProviderClient providerClient; Account testAccount = new Account(calendarName, CalendarContract.ACCOUNT_TYPE_LOCAL); LocalCalendar testCalendar; - - + + // helpers private Uri syncAdapterURI(Uri uri) { return uri.buildUpon() - .appendQueryParameter(Calendars.ACCOUNT_NAME, calendarName) .appendQueryParameter(Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL) + .appendQueryParameter(Calendars.ACCOUNT_NAME, accountName) .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true"). build(); } @@ -72,20 +81,21 @@ public class LocalCalendarTest extends InstrumentationTestCase { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) protected void setUp() throws Exception { - ContentResolver resolver = getInstrumentation().getContext().getContentResolver(); - providerClient = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY); + targetContext = getInstrumentation().getTargetContext(); + targetContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CALENDAR, "No privileges for enumerating calendars"); + + providerClient = targetContext.getContentResolver().acquireContentProviderClient(CalendarContract.AUTHORITY); - long id; + long calendarId; @Cleanup Cursor cursor = providerClient.query(Calendars.CONTENT_URI, - new String[]{Calendars._ID}, - Calendars.ACCOUNT_TYPE + "=? AND " + Calendars.NAME + "=?", - new String[]{ CalendarContract.ACCOUNT_TYPE_LOCAL, calendarName }, + new String[]{ Calendars._ID }, + Calendars.ACCOUNT_TYPE + "=? AND " + Calendars.ACCOUNT_NAME + "=? AND " + Calendars.NAME + "=?", + new String[] { CalendarContract.ACCOUNT_TYPE_LOCAL, accountName, calendarName }, null); if (cursor != null && cursor.moveToNext()) { - // found local test calendar - id = cursor.getLong(0); - Log.d(TAG, "Found test calendar with ID " + id); + calendarId = cursor.getLong(0); + Log.i(TAG, "Found test calendar with ID " + calendarId); } else { // no local test calendar found, create @@ -106,11 +116,11 @@ public class LocalCalendarTest extends InstrumentationTestCase { Uri calendarURI = providerClient.insert(syncAdapterURI(Calendars.CONTENT_URI), values); - id = ContentUris.parseId(calendarURI); - Log.d(TAG, "Created test calendar with ID " + id); + calendarId = ContentUris.parseId(calendarURI); + Log.d(TAG, "Created test calendar with ID " + calendarId); } - testCalendar = new LocalCalendar(testAccount, providerClient, id, null); + testCalendar = new LocalCalendar(testAccount, providerClient, calendarId, null); } protected void tearDown() throws Exception { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 767ca01b..186033fd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ { .withValue(entryColumnETag(), event.getETag()) .withValue(entryColumnUID(), event.getUid()); } else { - // this event is an exception for a recurring event -> calculate - // 1. ORIGINAL_INSTANCE_TIME when the original instance would have occured (ms UTC) - // 2. ORIGINAL_ALL_DAY was the original instance an all-day event? builder = builder.withValue(Events.ORIGINAL_SYNC_ID, event.getName()); // ORIGINAL_INSTANCE_TIME and ORIGINAL_ALL_DAY is set in buildExceptions. @@ -674,8 +671,6 @@ public class LocalCalendar extends LocalCollection { Date date = recurrenceId.getDate(); boolean originalAllDay = master.isAllDay(); - long originalInstanceTime; - if (originalAllDay && date instanceof DateTime) { String value = recurrenceId.getValue(); if (value.matches("^\\d{8}T\\d{6}$")) @@ -687,12 +682,9 @@ public class LocalCalendar extends LocalCollection { Log.e(TAG, "Couldn't parse DATE part of DATE-TIME RECURRENCE-ID", e); } } - originalInstanceTime = date.getTime(); - Log.i(TAG, "Original instance time: " + date.getTime()/1000); - builder.withValue(Events.ORIGINAL_INSTANCE_TIME, originalInstanceTime); + builder.withValue(Events.ORIGINAL_INSTANCE_TIME, date.getTime()); builder.withValue(Events.ORIGINAL_ALL_DAY, originalAllDay ? 1 : 0); - return builder; } diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java index 7710b269..57c16ca4 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java @@ -300,7 +300,7 @@ public abstract class LocalCollection { /** Updates the locally-known ETag of a resource. */ public void updateETag(Resource res, String eTag) throws LocalStorageException { - Log.d(TAG, "Setting ETag of local resource " + res + " to " + eTag); + Log.d(TAG, "Setting ETag of local resource " + res.getName() + " to " + eTag); ContentValues values = new ContentValues(1); values.put(entryColumnETag(), eTag);