Tests/Integration/test-caldav-scheduling.py:

Replace the tearDown code by something a bit more elegant:
    each test now adds its ics to the ics_list.
    tearDown loops over the list instead of listing each ics.

  2 new utility functions: _getAllEvents and _deleteAllEvent
  Those should probably be named _getCollectionContent and
  _deleteCollectionContent...

  For tests related to resources, make sure their calendar is empty
  before running them.
  This ensures we won't get conflicts with existing events...

  Various reindent

  New test for bug #1837. Fails on <=1.3.16

Monotone-Parent: 4b891748ee7ea0c409554e75a90fb995173562a2
Monotone-Revision: 802a8f25aa0ed67386953826b82939c3ab98bba2

Monotone-Author: jraby@inverse.ca
Monotone-Date: 2012-06-22T19:06:17
maint-2.0.2
Jean Raby 2012-06-22 19:06:17 +00:00
parent 7f3b99f2d4
commit cba2a7d458
1 changed files with 201 additions and 88 deletions

View File

@ -124,6 +124,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
self.user_calendar = "/SOGo/dav/%s/Calendar/personal/" % username
self.attendee1_calendar = "/SOGo/dav/%s/Calendar/personal/" % attendee1
self.attendee1_delegate_calendar = "/SOGo/dav/%s/Calendar/personal/" % attendee1_delegate
self.res_calendar = "/SOGo/dav/%s/Calendar/personal/" % resource_no_overbook
self.res_ob_calendar = "/SOGo/dav/%s/Calendar/personal/" % resource_can_overbook
# fetch non existing event to let sogo create the calendars in the db
self._getEvent(self.client, "%snonexistent" % self.user_calendar, exp_status=404)
@ -131,43 +133,24 @@ class CalDAVSchedulingTest(unittest.TestCase):
self._getEvent(self.attendee1_delegate_client, "%snonexistent" %
self.attendee1_delegate_calendar, exp_status=404)
# list of ics used by the test.
# tearDown will loop over this and wipe them in all users' calendar
self.ics_list = []
def tearDown(self):
self._deleteEvent(self.client,
"%stest-delegation.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-delegation.ics" % self.attendee1_calendar, None)
self._deleteEvent(self.attendee1_delegate_client,
"%stest-delegation.ics" % self.attendee1_delegate_calendar,
None)
self._deleteEvent(self.client,
"%stest-add-attendee.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-add-attendee.ics" % self.attendee1_calendar, None)
self._deleteEvent(self.client,
"%stest-no-overbook.ics" % self.user_calendar, None)
self._deleteEvent(self.client,
"%stest-no-overbook-overlap.ics" % self.user_calendar, None)
self._deleteEvent(self.client,
"%stest-can-overbook.ics" % self.user_calendar, None)
self._deleteEvent(self.client,
"%stest-can-overbook-overlap.ics" % self.user_calendar, None)
self._deleteEvent(self.client,
"%stest-rrule-exception-invitation-dance.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-rrule-exception-invitation-dance.ics" % self.attendee1_calendar, None)
self._deleteEvent(self.client,
"%stest-rrule-invitation-deleted-exdate-dance.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-rrule-invitation-deleted-exdate-dance.ics" % self.attendee1_calendar, None)
self._deleteEvent(self.client,
"%stest-organizer-is-attendee.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-organizer-is-attendee.ics" % self.attendee1_calendar, None)
self._deleteEvent(self.client,
"%stest-remove-attendee.ics" % self.user_calendar, None)
self._deleteEvent(self.attendee1_client,
"%stest-remove-attendee.ics" % self.attendee1_calendar, None)
# delete all created events from all users' calendar
for ics in self.ics_list:
self._deleteEvent(self.superuser_client,
"%s%s" % (self.user_calendar, ics), None)
self._deleteEvent(self.superuser_client,
"%s%s" % (self.attendee1_calendar, ics), None)
self._deleteEvent(self.superuser_client,
"%s%s" % (self.attendee1_delegate_calendar, ics), None)
self._deleteEvent(self.superuser_client,
"%s%s" % (self.res_calendar, ics), None)
self._deleteEvent(self.superuser_client,
"%s%s" % (self.res_ob_calendar, ics), None)
def _newEvent(self, summary="test event", uid="test", transp=0):
transparency = ("OPAQUE", "TRANSPARENT")
@ -227,6 +210,25 @@ class CalDAVSchedulingTest(unittest.TestCase):
if exp_status is not None:
self.assertEquals(delete.response["status"], exp_status)
def _getAllEvents(self, client, collection, exp_status = 207):
propfind = webdavlib.WebDAVPROPFIND(collection, None)
client.execute(propfind)
if exp_status is not None:
self.assertEquals(propfind.response["status"], exp_status)
content = []
nodes = propfind.response["document"].findall('{DAV:}response')
for node in nodes:
responseHref = node.find('{DAV:}href').text
content += [responseHref]
return content
def _deleteAllEvents(self, client, collection, exp_status = 204):
content = self._getAllEvents(client, collection)
for item in content:
self._deleteEvent(client, item)
def _eventAttendees(self, event):
attendees = {}
@ -277,6 +279,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
# make sure the event doesn't exist
ics_name = "test-add-attendee.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
self._deleteEvent(self.attendee1_client,
@ -312,6 +316,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
# make sure the event doesn't exist
ics_name = "test-remove-attendee.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
self._deleteEvent(self.attendee1_client,
@ -355,69 +361,79 @@ class CalDAVSchedulingTest(unittest.TestCase):
attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name), 404)
def testResourceNoOverbook(self):
""" try to overbook a resource """
""" try to overbook a resource """
# make sure the event doesn't exist
ics_name = "test-no-overbook.ics"
# make sure there are no events in the resource calendar
self._deleteAllEvents(self.superuser_client, self.res_calendar)
# make sure the event doesn't exist
ics_name = "test-no-overbook.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
ob_ics_name = "test-no-overbook-overlap.ics"
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
# 1. create an event in the organiser's calendar
event = self._newEvent(summary="Test no overbook", uid="test no overbook")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_no_ob_email
self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
# 2. create a second event overlapping the first one
event = self._newEvent(summary="Test no overbook - overlap", uid="test no overbook - overlap")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_no_ob_email
# put the event - should trigger a 403
self._putEvent(self.client, "%s%s" % (self.user_calendar, ob_ics_name), event, exp_status=403)
def testResourceCanOverbook(self):
""" try to overbook a resource - multiplebookings=0"""
# make sure the event doesn't exist
ics_name = "test-can-overbook.ics"
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
ob_ics_name = "test-can-overbook-overlap.ics"
ob_ics_name = "test-no-overbook-overlap.ics"
self.ics_list += [ob_ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ob_ics_name), None)
# 1. create an event in the organiser's calendar
event = self._newEvent(summary="Test can overbook", uid="test can overbook")
event = self._newEvent(summary="Test no overbook", uid="test no overbook")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_can_ob_name
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_can_ob_email
self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
attendee.value = self.res_no_ob_email
self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
# 2. create a second event overlapping the first one
event = self._newEvent(summary="Test can overbook - overlap", uid="test can overbook - overlap")
event = self._newEvent(summary="Test no overbook - overlap", uid="test no overbook - overlap")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_no_ob_email
# put the event - should trigger a 403
self._putEvent(self.client, "%s%s" % (self.user_calendar, ob_ics_name), event, exp_status=403)
def testResourceCanOverbook(self):
""" try to overbook a resource - multiplebookings=0"""
# make sure there are no events in the resource calendar
self._deleteAllEvents(self.superuser_client, self.res_ob_calendar)
# make sure the event doesn't exist
ics_name = "test-can-overbook.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
ob_ics_name = "test-can-overbook-overlap.ics"
self.ics_list += [ob_ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ob_ics_name), None)
# 1. create an event in the organiser's calendar
event = self._newEvent(summary="Test can overbook", uid="test can overbook")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_can_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_can_ob_email
self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
# 2. create a second event overlapping the first one
event = self._newEvent(summary="Test can overbook - overlap", uid="test can overbook - overlap")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
@ -427,8 +443,97 @@ class CalDAVSchedulingTest(unittest.TestCase):
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_can_ob_email
# put the event - should be fine since we can overbook this one
self._putEvent(self.client, "%s%s" % (self.user_calendar, ob_ics_name), event)
# put the event - should be fine since we can overbook this one
self._putEvent(self.client, "%s%s" % (self.user_calendar, ob_ics_name), event)
def testResourceBookingOverlapDetection(self):
""" Resource booking overlap detection - bug #1837"""
# There used to be some problems with recurring events and resources booking
# This test implements these edge cases
# 1. Create recurring event (with resource)
# 2. Create single event overlaping one instance for the previous event
# (should fail)
# 3. Create recurring event which _doesn't_ overlap the first event
# (should be OK, used to fail pre1.3.17)
# 4. Create recurring event overlapping the previous recurring event
# (should fail)
# make sure there are no events in the resource calendar
self._deleteAllEvents(self.superuser_client, self.res_calendar)
# make sure the event doesn't exist
ics_name = "test-res-overlap-detection.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,ics_name), None)
overlap_ics_name = "test-res-overlap-detection-overlap.ics"
self.ics_list += [overlap_ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.attendee1_calendar,overlap_ics_name), None)
nooverlap_recurring_ics_name = "test-res-overlap-detection-nooverlap.ics"
self.ics_list += [nooverlap_recurring_ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,nooverlap_recurring_ics_name), None)
overlap_recurring_ics_name = "test-res-overlap-detection-overlap-recurring.ics"
self.ics_list += [overlap_recurring_ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar,overlap_recurring_ics_name), None)
# 1. create recurring event with resource
event = self._newEvent(summary="recurring event with resource",
uid="recurring event w resource")
event.vevent.add('rrule').value = "FREQ=DAILY;COUNT=5"
organizer = event.vevent.add('organizer')
organizer.cn_param = self.user_name
organizer.value = self.user_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_no_ob_email
# keep a copy around for #3
nooverlap_event = vobject.iCalendar()
nooverlap_event.copy(event)
self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event)
# 2. Create single event overlaping one instance for the previous event
event = self._newEvent(summary="recurring event with resource",
uid="recurring event w resource - overlap")
organizer = event.vevent.add('organizer')
organizer.cn_param = self.attendee1_name
organizer.value = self.attendee1_email
attendee = event.vevent.add('attendee')
attendee.cn_param = self.res_no_ob_name
attendee.rsvp_param = "TRUE"
attendee.partstat_param = "NEEDS-ACTION"
attendee.value = self.res_no_ob_email
# should fail
self._putEvent(self.client, "%s%s" % (self.attendee1_calendar, overlap_ics_name), event, exp_status=403)
# 3. Create recurring event which _doesn't_ overlap the first event
# (should be OK, used to fail pre1.3.17)
# shift the start date to one hour after the original event end time
nstartdate = nooverlap_event.vevent.dtend.value + datetime.timedelta(0, 3600)
nooverlap_event.vevent.dtstart.value = nstartdate
nooverlap_event.vevent.dtend.value = nstartdate + datetime.timedelta(0, 3600)
nooverlap_event.vevent.uid.value = "recurring - nooverlap"
self._putEvent(self.client, "%s%s" % (self.user_calendar, nooverlap_recurring_ics_name), nooverlap_event)
# 4. Create recurring event overlapping the previous recurring event
# should fail
nstartdate = nooverlap_event.vevent.dtstart.value + datetime.timedelta(0, 300)
nooverlap_event.vevent.dtstart.value = nstartdate
nooverlap_event.vevent.dtend.value = nstartdate + datetime.timedelta(0, 3600)
nooverlap_event.vevent.uid.value = "recurring - overlap"
self._putEvent(self.client, "%s%s" % (self.user_calendar, overlap_recurring_ics_name), nooverlap_event, exp_status=403)
def testRruleExceptionInvitationDance(self):
@ -448,6 +553,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
# bob isn't in the master+exception event
ics_name = "test-rrule-exception-invitation-dance.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar, ics_name), None)
self._deleteEvent(self.attendee1_client,
@ -570,6 +677,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
# and that bob is 'declined'
ics_name = "test-rrule-invitation-deleted-exdate-dance.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar, ics_name), None)
self._deleteEvent(self.attendee1_client,
@ -644,6 +753,8 @@ class CalDAVSchedulingTest(unittest.TestCase):
# 1. create an event, add an attendee and add the organizer as an attendee
# 2. SOGo should remove the organizer from the attendee list
ics_name = "test-organizer-is-attendee.ics"
self.ics_list += [ics_name]
self._deleteEvent(self.client,
"%s%s" % (self.user_calendar, ics_name), None)
self._deleteEvent(self.attendee1_client,
@ -683,14 +794,16 @@ class CalDAVSchedulingTest(unittest.TestCase):
def testInvitationDelegation(self):
""" invitation delegation """
ics_name = "test-delegation.ics"
self.ics_list += [ics_name]
# the invitation must not exist
self._deleteEvent(self.client,
"%stest-delegation.ics" % self.user_calendar, None)
"%s%s" % (self.user_calendar, ics_name), None)
self._deleteEvent(self.attendee1_client,
"%stest-delegation.ics" % self.attendee1_calendar, None)
"%s%s" % (self.attendee1_calendar, ics_name), None)
self._deleteEvent(self.attendee1_delegate_client,
"%stest-delegation.ics" % self.attendee1_delegate_calendar,
None)
"%s%s" % (self.attendee1_delegate_calendar, ics_name), None)
# 1. org -> attendee => org: 1, attendee: 1 (pst=N-A), delegate: 0