Fix conflict detection

Fix conflict detection by providing finer rules. Meetings on alternating
weeks no longer conflict. Meetings on overlapping times now conflict.

Add proper tests to check all combinations.

Change-Id: I069cdd40fecb5fd7a2ab828a495bdf627ca1a811
This commit is contained in:
Thierry Carrez 2015-02-25 12:16:50 +01:00
parent d6963905f1
commit 40f12c0d63
3 changed files with 73 additions and 22 deletions

View File

@ -28,15 +28,17 @@ class Schedule(object):
self.time = datetime.datetime.strptime(sched_yaml['time'], '%H%M')
self.day = sched_yaml['day']
self.irc = sched_yaml['irc']
self.freq = sched_yaml['frequency']
self.recurrence = supported_recurrences[sched_yaml['frequency']]
def __eq__(self, other):
#TODO(ttx): This is a bit overzealous (it will report as conflict
# biweekly-odd/biweekly-even on same date/hour/irc) so this should be
# revamped especially if we want to add more complex recurrence rules
return ((self.day == other.day) and
(self.time == other.time) and
(self.irc == other.irc))
def conflicts(self, other):
"""Checks for conflicting schedules."""
alternating = set(['biweekly-odd', 'biweekly-even'])
return (
((self.day == other.day) and
(abs(self.time - other.time) < datetime.timedelta(hours=1)) and
(self.irc == other.irc)) and
(set([self.freq, other.freq]) != alternating))
class Meeting(object):
@ -106,7 +108,7 @@ def check_for_meeting_conflicts(meetings):
other_schedules = meetings[j].schedules
for schedule in schedules:
for other_schedule in other_schedules:
if schedule == other_schedule:
if schedule.conflicts(other_schedule):
msg_dict = {'one': schedule.filefrom,
'two': other_schedule.filefrom}
raise MeetingConflictError(

View File

@ -14,7 +14,7 @@
"""Sample meeting data to use for testing."""
FIRST_MEETING_YAML = """
WEEKLY_MEETING = """
project: OpenStack Subteam Meeting
schedule:
- time: '1200'
@ -28,10 +28,10 @@ agenda: |
* Top bugs this week
"""
SECOND_MEETING_YAML = """
CONFLICTING_WEEKLY_MEETING = """
project: OpenStack Subteam Meeting 2
schedule:
- time: '1200'
- time: '1230'
day: Wednesday
irc: openstack-meeting
frequency: weekly
@ -42,7 +42,7 @@ agenda: |
* New features
"""
THIRD_MEETING_YAML = """
WEEKLY_OTHER_CHANNEL_MEETING = """
project: OpenStack Subteam Meeting 3
schedule:
- time: '1200'
@ -56,13 +56,40 @@ agenda: |
* New features
"""
BIWEEKLY_MEETING_YAML = """
ALTERNATING_MEETING = """
project: OpenStack Subteam Meeting
schedule:
- time: '1200'
day: Wednesday
irc: openstack-meeting
frequency: biweekly-even
- time: '2200'
day: Wednesday
irc: openstack-meeting
frequency: biweekly-odd
chair: Jane Developer
description: >
Weekly meeting for Subteam project.
agenda: |
* Top bugs this week
"""
BIWEEKLY_EVEN_MEETING = """
project: OpenStack Subteam 12 Meeting
schedule:
- time: '2200'
day: Wednesday
irc: openstack-meeting
frequency: biweekly-even
chair: Jane Developer
description: >
Weekly meeting for Subteam project.
agenda: |
* Top bugs this week
"""
BIWEEKLY_ODD_MEETING = """
project: OpenStack Subteam 12 Meeting
schedule:
- time: '2200'
day: Wednesday

View File

@ -19,24 +19,46 @@ from yaml2ical.tests import sample_data
class MeetingTestCase(unittest.TestCase):
def test_load_yaml_file(self):
m = meeting.load_meetings(sample_data.FIRST_MEETING_YAML)[0]
m = meeting.load_meetings(sample_data.WEEKLY_MEETING)[0]
self.assertEqual('OpenStack Subteam Meeting', m.project)
self.assertEqual('Joe Developer', m.chair)
self.assertEqual('Weekly meeting for Subteam project.\n',
m.description)
def test_exception_raised_when_conflict_detected(self):
"""Exception is raised when a meeting conflict is detected."""
meeting_one = meeting.load_meetings(sample_data.FIRST_MEETING_YAML)
meeting_two = meeting.load_meetings(sample_data.SECOND_MEETING_YAML)
def should_be_conflicting(self, yaml1, yaml2):
"""Exception is raised when meetings should conflict."""
meeting_one = meeting.load_meetings(yaml1)
meeting_two = meeting.load_meetings(yaml2)
meeting_list = [meeting_one.pop(), meeting_two.pop()]
self.assertRaises(meeting.MeetingConflictError,
meeting.check_for_meeting_conflicts,
meeting_list)
def test_no_exception_raised_with_diff_irc_rooms(self):
"""No exception raised when using different IRC rooms."""
meeting_one = meeting.load_meetings(sample_data.FIRST_MEETING_YAML)
meeting_two = meeting.load_meetings(sample_data.THIRD_MEETING_YAML)
def should_not_conflict(self, yaml1, yaml2):
"""No exception raised when meetings shouldn't conflict."""
meeting_one = meeting.load_meetings(yaml1)
meeting_two = meeting.load_meetings(yaml2)
meeting_list = [meeting_one.pop(), meeting_two.pop()]
meeting.check_for_meeting_conflicts(meeting_list)
def test_weekly_conflict(self):
self.should_be_conflicting(
sample_data.WEEKLY_MEETING,
sample_data.CONFLICTING_WEEKLY_MEETING)
self.should_not_conflict(
sample_data.WEEKLY_MEETING,
sample_data.WEEKLY_OTHER_CHANNEL_MEETING)
def test_biweekly_conflict(self):
self.should_be_conflicting(
sample_data.WEEKLY_MEETING,
sample_data.ALTERNATING_MEETING)
self.should_not_conflict(
sample_data.ALTERNATING_MEETING,
sample_data.BIWEEKLY_EVEN_MEETING)
self.should_be_conflicting(
sample_data.ALTERNATING_MEETING,
sample_data.BIWEEKLY_ODD_MEETING)
self.should_not_conflict(
sample_data.BIWEEKLY_ODD_MEETING,
sample_data.BIWEEKLY_EVEN_MEETING)