def test_acceptInvitation(self): """ If the client is an attendee on an event and the PARTSTAT is NEEDS-ACTION, a response is generated which accepts the invitation and the corresponding event in the I{schedule-inbox} is deleted. """ clock = Clock() randomDelay = 7 vevent = Component.fromString(INVITED_EVENT) attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1]) client = StubClient(userNumber, self.mktemp()) calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client._calendars[calendarURL] = calendar inboxURL = '/some/inbox/' inbox = Calendar(caldavxml.schedule_inbox, set(), u'the inbox', inboxURL, None) client._calendars[inboxURL] = inbox event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._setEvent(event.url, event) inboxEvent = Event(client.serializeLocation(), inboxURL + u'4321.ics', None, vevent) client._setEvent(inboxEvent.url, inboxEvent) accepter = Accepter(clock, self.sim, client, userNumber) accepter.setParameters( acceptDelayDistribution=Deterministic(randomDelay)) accepter.eventChanged(event.url) clock.advance(randomDelay) vevent = client._events[event.url].component attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) self.assertEquals(len(attendees), 2) self.assertEquals(attendees[1].parameterValue('CN'), 'User %02d' % (userNumber, )) self.assertEquals(attendees[1].parameterValue('PARTSTAT'), 'ACCEPTED') self.assertFalse(attendees[1].hasParameter('RSVP')) self.assertNotIn(inboxEvent.url, client._events) self.assertNotIn('4321.ics', inbox.events)
def test_changeEventAttendeePreconditionFailed(self): """ If the attempt to accept an invitation fails because of an unmet precondition (412), the event is re-retrieved and the PUT is re-issued with the new data. """ clock = Clock() userNumber = 2 client = StubClient(userNumber, self.mktemp()) randomDelay = 3 calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client._calendars[calendarURL] = calendar vevent = Component.fromString(INVITED_EVENT) event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._setEvent(event.url, event) accepter = Accepter(clock, self.sim, client, userNumber) accepter.setParameters( acceptDelayDistribution=Deterministic(randomDelay)) client.rescheduled.add(event.url) accepter.eventChanged(event.url) clock.advance(randomDelay)
def test_inboxReplyFailedDelete(self): """ When an inbox item that contains a reply is seen by the client, it deletes it immediately. If the delete fails, the appropriate response code is returned. """ userNumber = 1 clock = Clock() inboxURL = '/some/inbox/' vevent = Component.fromString(INBOX_REPLY) inbox = Calendar(caldavxml.schedule_inbox, set(), u'the inbox', inboxURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[inboxURL] = inbox inboxEvent = Event(client.serializeLocation(), inboxURL + u'4321.ics', None, vevent) client._setEvent(inboxEvent.url, inboxEvent) client._failDeleteWithObject( inboxEvent.url, IncorrectResponseCode( NO_CONTENT, Response(('HTTP', 1, 1), PRECONDITION_FAILED, 'Precondition Failed', None, None))) accepter = Accepter(clock, self.sim, client, userNumber) accepter.eventChanged(inboxEvent.url) clock.advance(3) self.assertNotIn(inboxEvent.url, client._events) self.assertNotIn('4321.ics', inbox.events)
def test_ignoreAlreadyAccepting(self): """ If the client sees an event change a second time before responding to an invitation found on it during the first change notification, the second change notification does not generate another accept attempt. """ clock = Clock() randomDelay = 7 vevent = Component.fromString(INVITED_EVENT) attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1]) calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[calendarURL] = calendar event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._events[event.url] = event accepter = Accepter(clock, self.sim, client, userNumber) accepter.random = Deterministic() accepter.random.gauss = lambda mu, sigma: randomDelay accepter.eventChanged(event.url) accepter.eventChanged(event.url) clock.advance(randomDelay)
def _simpleAccount(self, userNumber, eventText): client = StubClient(userNumber, self.mktemp()) vevent = Component.fromString(eventText) calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', u'/cal/', None) event = Event(client.serializeLocation(), calendar.url + u'1234.ics', None, vevent) calendar.events = {u'1234.ics': event} client._events.update({event.url: event}) client._calendars.update({calendar.url: calendar}) return vevent, event, calendar, client
def test_ignoreAccepted(self): """ If the client is an attendee on an event but the PARTSTAT is not NEEDS-ACTION, the event is ignored. """ vevent = Component.fromString(ACCEPTED_EVENT) attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1]) calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[calendarURL] = calendar event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._events[event.url] = event accepter = Accepter(None, self.sim, client, userNumber) accepter.eventChanged(event.url)
def test_reacceptInvitation(self): """ If a client accepts an invitation on an event and then is later re-invited to the same event, the invitation is again accepted. """ clock = Clock() randomDelay = 7 vevent = Component.fromString(INVITED_EVENT) attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1]) calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[calendarURL] = calendar event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._events[event.url] = event accepter = Accepter(clock, self.sim, client, userNumber) accepter.setParameters( acceptDelayDistribution=Deterministic(randomDelay)) accepter.eventChanged(event.url) clock.advance(randomDelay) # Now re-set the event so it has to be accepted again event.component = Component.fromString(INVITED_EVENT) # And now re-deliver it accepter.eventChanged(event.url) clock.advance(randomDelay) # And ensure that it was accepted again vevent = client._events[event.url].component attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) self.assertEquals(len(attendees), 2) self.assertEquals(attendees[1].parameterValue('CN'), 'User %02d' % (userNumber, )) self.assertEquals(attendees[1].parameterValue('PARTSTAT'), 'ACCEPTED') self.assertFalse(attendees[1].hasParameter('RSVP'))
def test_inboxReply(self): """ When an inbox item that contains a reply is seen by the client, it deletes it immediately. """ userNumber = 1 clock = Clock() inboxURL = '/some/inbox/' vevent = Component.fromString(INBOX_REPLY) inbox = Calendar(caldavxml.schedule_inbox, set(), u'the inbox', inboxURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[inboxURL] = inbox inboxEvent = Event(client.serializeLocation(), inboxURL + u'4321.ics', None, vevent) client._setEvent(inboxEvent.url, inboxEvent) accepter = Accepter(clock, self.sim, client, userNumber) accepter.eventChanged(inboxEvent.url) clock.advance(3) self.assertNotIn(inboxEvent.url, client._events) self.assertNotIn('4321.ics', inbox.events)
def addEvent(self, href, vevent): self._events[href] = Event(self.serializePath, href, None, vevent) return succeed(None)