[CalendarServer-changes] [13931] CalendarServer/trunk/txdav/caldav/datastore
source_changes at macosforge.org
source_changes at macosforge.org
Tue Sep 2 11:56:19 PDT 2014
Revision: 13931
http://trac.calendarserver.org//changeset/13931
Author: cdaboo at apple.com
Date: 2014-09-02 11:56:19 -0700 (Tue, 02 Sep 2014)
Log Message:
-----------
Make sure free busy updates properly when overridden instances are added/removed from an auto-accept attendee.
Modified Paths:
--------------
CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py
CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icaldiff.py
CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py 2014-09-02 18:53:50 UTC (rev 13930)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/icaldiff.py 2014-09-02 18:56:19 UTC (rev 13931)
@@ -770,16 +770,28 @@
# Now verify that each additional component in oldset matches a derived component in newset
for key in oldset - newset:
+ rid = key[2]
oldcomponent = oldmap[key]
- newcomponent = self.newcalendar.deriveInstance(key[2])
+ newcomponent = self.newcalendar.deriveInstance(rid)
if newcomponent is None:
+ # For the non iTIP case we must report missing components on either side. Marking
+ # the DTSTART as changed is enough to trigger logic in the caller to treat this
+ # as a significant change.
+ if not isiTip:
+ rids[rid.getText() if rid is not None else ""] = {"DTSTART": set()}
continue
self._diffComponents(oldcomponent, newcomponent, rids, isiTip)
# Now verify that each additional component in oldset matches a derived component in newset
for key in newset - oldset:
- oldcomponent = self.oldcalendar.deriveInstance(key[2])
+ rid = key[2]
+ oldcomponent = self.oldcalendar.deriveInstance(rid)
if oldcomponent is None:
+ # For the non iTIP case we must report missing components on either side. Marking
+ # the DTSTART as changed is enough to trigger logic in the caller to treat this
+ # as a significant change.
+ if not isiTip:
+ rids[rid.getText() if rid is not None else ""] = {"DTSTART": set()}
continue
newcomponent = newmap[key]
self._diffComponents(oldcomponent, newcomponent, rids, isiTip)
Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py 2014-09-02 18:53:50 UTC (rev 13930)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py 2014-09-02 18:56:19 UTC (rev 13931)
@@ -43,7 +43,6 @@
import hashlib
import json
import uuid
-import time
"""
CalDAV implicit processing.
@@ -755,9 +754,7 @@
end=str(makeTimedUTC(instance.end)),
)
- t = time.time()
yield generateFreeBusyInfo(testcal, fbinfo, tr, 0, uid, servertoserver=True, accountingItems=accounting if len(instances) == 1 else None)
- print time.time() - t
# If any fbinfo entries exist we have an overlap
if len(fbinfo[0]) or len(fbinfo[1]) or len(fbinfo[2]):
Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icaldiff.py 2014-09-02 18:53:50 UTC (rev 13930)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/test/test_icaldiff.py 2014-09-02 18:56:19 UTC (rev 13931)
@@ -4520,13 +4520,164 @@
),
)
- for description, calendar1, calendar2, rids in itertools.chain(data1, data2, data3,):
+ data4 = (
+ (
+ "#4.1 Override component removed",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {},
+ ),
+ (
+ "#4.2 Override component added",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+SUMMARY:Test
+END:VCALENDAR
+""",
+ {},
+ ),
+ )
+
+ data5 = (
+ (
+ "#5.1 Override component removed",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {"20080602T120000Z": {"DTSTART": set()}},
+ ),
+ (
+ "#5.2 Override component added",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+SUMMARY:Test
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T130000Z
+DTEND:20080602T140000Z
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+ {"20080602T120000Z": {"DTSTART": set()}},
+ ),
+ )
+
+ for description, calendar1, calendar2, rids in itertools.chain(data1, data2, data3, data4,):
differ = iCalDiff(Component.fromString(calendar1), Component.fromString(calendar2), False)
got_rids = differ.whatIsDifferent()
rids = dict([(DateTime.parseText(k) if k else None, v) for k, v in rids.items()])
self.assertEqual(got_rids, rids, msg="%s expected R-IDs: '%s', got: '%s'" % (description, rids, got_rids,))
+ for description, calendar1, calendar2, rids in itertools.chain(data5,):
+ differ = iCalDiff(Component.fromString(calendar1), Component.fromString(calendar2), False)
+ got_rids = differ.whatIsDifferent(isiTip=False)
+ self.assertEqual(got_rids, rids, msg="%s expected R-IDs: '%s', got: '%s'" % (description, rids, got_rids,))
+
def test_attendee_needs_action(self):
data = (
Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py 2014-09-02 18:53:50 UTC (rev 13930)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py 2014-09-02 18:56:19 UTC (rev 13931)
@@ -7003,7 +7003,7 @@
class TimeRangeUpdateOptimization(CommonCommonTests, unittest.TestCase):
"""
- CalendarObject splitting tests
+ CalendarObject time range optimization tests.
"""
EVENT1 = """BEGIN:VCALENDAR
@@ -7174,13 +7174,17 @@
self.now = DateTime.getNowUTC()
self.now.setDateOnly(True)
+ self.now1 = self.now.duplicate()
+ self.now1.offsetDay(1)
+ self.now2 = self.now.duplicate()
+ self.now2.offsetDay(2)
self.trcount = 0
base_addInstances = CalendarObject._addInstances
- def __addInstances(*args):
+ def _addInstances(*args):
self.trcount += 1
return base_addInstances(*args)
- self.patch(CalendarObject, "_addInstances", __addInstances)
+ self.patch(CalendarObject, "_addInstances", _addInstances)
self.patch(config, "FreeBusyIndexDelayedExpand", False)
self.patch(config, "FreeBusyIndexSmartUpdate", True)
@@ -7489,7 +7493,7 @@
@inlineCallbacks
def test_schedulingPUT(self):
"""
- Test that second PUT withe time change causes a TIME_RANGE update
+ Test that second PUT with time change causes a TIME_RANGE update
"""
# Need schedule-q off for this test
@@ -7529,7 +7533,7 @@
@inlineCallbacks
def test_schedulingPUT_withoutOptimization(self):
"""
- Test that second PUT withe time change causes a TIME_RANGE update
+ Test that second PUT with time change causes a TIME_RANGE update
"""
self.patch(config, "FreeBusyIndexSmartUpdate", False)
@@ -7566,3 +7570,189 @@
yield self.commit()
self.assertEqual(self.trcount, 11)
+
+
+ INVITE_OVERRIDE1 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+DTSTART:{now}T120000Z
+DURATION:PT1H
+SUMMARY:New Event
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now1}T120000Z
+DTSTART:{now1}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now1
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:urn:x-uid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+"""
+
+ INVITE_OVERRIDE2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now1}T120000Z
+DTSTART:{now1}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now1
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+"""
+
+ INVITE_OVERRIDE3 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+DTSTART:{now}T120000Z
+DURATION:PT1H
+SUMMARY:New Event
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now1}T120000Z
+DTSTART:{now1}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now1
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now2}T120000Z
+DTSTART:{now2}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now2
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:urn:x-uid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+"""
+
+ INVITE_OVERRIDE4 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+DTSTART:{now}T120000Z
+DURATION:PT1H
+SUMMARY:New Event
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now1}T120000Z
+DTSTART:{now1}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now1
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100203T013849Z
+UID:uid1
+RECURRENCE-ID:{now2}T120000Z
+DTSTART:{now2}T120000Z
+DURATION:PT1H
+SUMMARY:New Event now2
+DTSTAMP:20100203T013909Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+"""
+
+
+ @inlineCallbacks
+ def test_schedulingPUT_AddRemoveOverride_AutoAccept(self):
+ """
+ Test that second PUT with override change causes a TIME_RANGE update
+ """
+
+ # Need schedule-q off for this test
+ self.patch(config.Scheduling.Options.WorkQueues, "Enabled", False)
+ self.patch(config.Scheduling.Options.WorkQueues, "AutoReplyDelaySeconds", 1)
+
+ # First PUT causes T-R change
+ cal = yield self.calendarUnderTest(home="user01", name="calendar")
+ yield cal.createObjectResourceWithName("1.ics", Component.fromString(self.INVITE_OVERRIDE1.format(
+ now=self.now.getText(),
+ now1=self.now1.getText(),
+ now2=self.now2.getText(),
+ )))
+ yield self.commit()
+
+ # Wait for it to complete
+ yield JobItem.waitEmpty(self._sqlCalendarStore.newTransaction, reactor, 60)
+
+ self.assertEqual(self.trcount, 3)
+
+ # Organizer adds attendee to override causes T-R change (except for their item)
+ cobj = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar")
+ yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE3.format(
+ now=self.now.getText(),
+ now1=self.now1.getText(),
+ now2=self.now2.getText(),
+ )))
+ yield self.commit()
+
+ # Wait for it to complete
+ yield JobItem.waitEmpty(self._sqlCalendarStore.newTransaction, reactor, 60)
+
+ self.assertEqual(self.trcount, 5)
+
+ # Organizer removes attendee from override causes T-R change (except for their item)
+ cobj = yield self.calendarObjectUnderTest(home="user01", calendar_name="calendar")
+ yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE4.format(
+ now=self.now.getText(),
+ now1=self.now1.getText(),
+ now2=self.now2.getText(),
+ )))
+ yield self.commit()
+
+ # Wait for it to complete
+ yield JobItem.waitEmpty(self._sqlCalendarStore.newTransaction, reactor, 60)
+
+ self.assertEqual(self.trcount, 6)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140902/b33d02aa/attachment-0001.html>
More information about the calendarserver-changes
mailing list