1 /*
2   SPDX-FileCopyrightText: 2010 Casey Link <unnamedrambler@gmail.com>
3   SPDX-FileCopyrightText: 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
4 
5   SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "conflictresolvertest.h"
9 #include "conflictresolver.h"
10 
11 #include <KCalendarCore/Duration>
12 #include <KCalendarCore/Event>
13 #include <KCalendarCore/Period>
14 
15 #include <QTest>
16 #include <QWidget>
17 
18 using namespace IncidenceEditorNG;
19 
insertAttendees()20 void ConflictResolverTest::insertAttendees()
21 {
22     for (const CalendarSupport::FreeBusyItem::Ptr &item : std::as_const(attendees)) {
23         resolver->insertAttendee(item);
24     }
25 }
26 
addAttendee(const QString & email,const KCalendarCore::FreeBusy::Ptr & fb,KCalendarCore::Attendee::Role role)27 void ConflictResolverTest::addAttendee(const QString &email, const KCalendarCore::FreeBusy::Ptr &fb, KCalendarCore::Attendee::Role role)
28 {
29     QString name = QStringLiteral("attendee %1").arg(attendees.count());
30     CalendarSupport::FreeBusyItem::Ptr item(
31         new CalendarSupport::FreeBusyItem(KCalendarCore::Attendee(name, email, false, KCalendarCore::Attendee::Accepted, role), nullptr));
32     item->setFreeBusy(KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(*fb.data())));
33     attendees << item;
34 }
35 
initTestCase()36 void ConflictResolverTest::initTestCase()
37 {
38     parent = new QWidget;
39     init();
40 }
41 
init()42 void ConflictResolverTest::init()
43 {
44     base = QDateTime::currentDateTime().addDays(1);
45     end = base.addSecs(10 * 60 * 60);
46     resolver = new ConflictResolver(parent, parent);
47 }
48 
cleanup()49 void ConflictResolverTest::cleanup()
50 {
51     delete resolver;
52     resolver = nullptr;
53     attendees.clear();
54 }
55 
simpleTest()56 void ConflictResolverTest::simpleTest()
57 {
58     KCalendarCore::Period meeting(end.addSecs(-3 * 60 * 60), KCalendarCore::Duration(2 * 60 * 60));
59     addAttendee(QStringLiteral("albert@einstein.net"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting)));
60 
61     insertAttendees();
62 
63     static const int resolution = 15 * 60;
64     resolver->setResolution(resolution);
65     resolver->setEarliestDateTime(base);
66     resolver->setLatestDateTime(end);
67     resolver->findAllFreeSlots();
68 
69     QVERIFY(resolver->availableSlots().size() == 2);
70 
71     KCalendarCore::Period first = resolver->availableSlots().at(0);
72     QCOMPARE(first.start(), base);
73     QCOMPARE(first.end(), meeting.start());
74 
75     KCalendarCore::Period second = resolver->availableSlots().at(1);
76     QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue);
77     QCOMPARE(second.start(), meeting.end().addSecs(resolution)); // add 15 minutes because the
78     // free block doesn't start until
79     // the next timeslot
80     QCOMPARE(second.end(), end);
81 }
82 
stillPrettySimpleTest()83 void ConflictResolverTest::stillPrettySimpleTest()
84 {
85     KCalendarCore::Period meeting1(base, KCalendarCore::Duration(2 * 60 * 60));
86     KCalendarCore::Period meeting2(base.addSecs(60 * 60), KCalendarCore::Duration(2 * 60 * 60));
87     KCalendarCore::Period meeting3(end.addSecs(-3 * 60 * 60), KCalendarCore::Duration(2 * 60 * 60));
88     addAttendee(QStringLiteral("john.f@kennedy.com"),
89                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting1 << meeting3)));
90     addAttendee(QStringLiteral("elvis@rock.com"),
91                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting2 << meeting3)));
92     addAttendee(QStringLiteral("albert@einstein.net"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting3)));
93 
94     insertAttendees();
95 
96     static const int resolution = 15 * 60;
97     resolver->setResolution(resolution);
98     resolver->setEarliestDateTime(base);
99     resolver->setLatestDateTime(end);
100     resolver->findAllFreeSlots();
101 
102     QVERIFY(resolver->availableSlots().size() == 2);
103 
104     KCalendarCore::Period first = resolver->availableSlots().at(0);
105     QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue);
106     QCOMPARE(first.start(), meeting2.end().addSecs(resolution));
107     QCOMPARE(first.end(), meeting3.start());
108 
109     KCalendarCore::Period second = resolver->availableSlots().at(1);
110     QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue);
111     QCOMPARE(second.start(), meeting3.end().addSecs(resolution)); // add 15 minutes because the
112     // free block doesn't start until
113     // the next timeslot
114     QCOMPARE(second.end(), end);
115 }
116 
117 #define _time(h, m) QDateTime(base.date(), QTime(h, m))
118 
akademy2010()119 void ConflictResolverTest::akademy2010()
120 {
121     // based off akademy 2010 schedule
122 
123     // first event was at 9:30, so lets align our start time there
124     base.setTime(QTime(9, 30));
125     end = base.addSecs(8 * 60 * 60);
126     KCalendarCore::Period opening(_time(9, 30), _time(9, 45));
127     KCalendarCore::Period keynote(_time(9, 45), _time(10, 30));
128 
129     KCalendarCore::Period sevenPrinciples(_time(10, 30), _time(11, 15));
130     KCalendarCore::Period commAsService(_time(10, 30), _time(11, 15));
131 
132     KCalendarCore::Period kdeForums(_time(11, 15), _time(11, 45));
133     KCalendarCore::Period oviStore(_time(11, 15), _time(11, 45));
134 
135     // 10 min break
136 
137     KCalendarCore::Period highlights(_time(12, 0), _time(12, 45));
138     KCalendarCore::Period styles(_time(12, 0), _time(12, 45));
139 
140     KCalendarCore::Period wikimedia(_time(12, 45), _time(13, 15));
141     KCalendarCore::Period avalanche(_time(12, 45), _time(13, 15));
142 
143     KCalendarCore::Period pimp(_time(13, 15), _time(13, 45));
144     KCalendarCore::Period direction(_time(13, 15), _time(13, 45));
145 
146     // lunch 1 hr 25 min lunch
147 
148     KCalendarCore::Period blurr(_time(15, 15), _time(16, 00));
149     KCalendarCore::Period plasma(_time(15, 15), _time(16, 00));
150 
151     //  for ( int i = 1; i < 80; ++i ) {
152     // adds 80 people (adds the same 8 people 10 times)
153     addAttendee(
154         QStringLiteral("akademyattendee1@email.com"),
155         KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << wikimedia << direction)));
156     addAttendee(
157         QStringLiteral("akademyattendee2@email.com"),
158         KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << commAsService << highlights << pimp)));
159     addAttendee(QStringLiteral("akademyattendee3@email.com"),
160                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << kdeForums << styles << pimp << plasma)));
161     addAttendee(QStringLiteral("akademyattendee4@email.com"),
162                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << pimp << blurr)));
163     addAttendee(QStringLiteral("akademyattendee5@email.com"),
164                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << keynote << oviStore << highlights << avalanche)));
165     addAttendee(QStringLiteral("akademyattendee6@email.com"),
166                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << commAsService << highlights)));
167     addAttendee(QStringLiteral("akademyattendee7@email.com"),
168                 KCalendarCore::FreeBusy::Ptr(
169                     new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << kdeForums << styles << avalanche << pimp << plasma)));
170     addAttendee(
171         QStringLiteral("akademyattendee8@email.com"),
172         KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << wikimedia << blurr)));
173     //  }
174 
175     insertAttendees();
176 
177     const int resolution = 5 * 60;
178     resolver->setResolution(resolution);
179     resolver->setEarliestDateTime(base);
180     resolver->setLatestDateTime(end);
181     // QBENCHMARK {
182     resolver->findAllFreeSlots();
183     // }
184 
185     QVERIFY(resolver->availableSlots().size() == 3);
186     QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Abort);
187     QCOMPARE(resolver->availableSlots().at(0).duration(), KCalendarCore::Duration(10 * 60));
188     QCOMPARE(resolver->availableSlots().at(1).duration(), KCalendarCore::Duration(1 * 60 * 60 + 25 * 60));
189     QVERIFY(resolver->availableSlots().at(2).start() > plasma.end());
190 }
191 
testPeriodIsLargerThenTimeframe()192 void ConflictResolverTest::testPeriodIsLargerThenTimeframe()
193 {
194     base.setDate(QDate(2010, 7, 29));
195     base.setTime(QTime(7, 30));
196 
197     end.setDate(QDate(2010, 7, 29));
198     end.setTime(QTime(8, 30));
199 
200     KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45));
201 
202     addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"),
203                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent)));
204     addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List())));
205 
206     insertAttendees();
207     resolver->setEarliestDateTime(base);
208     resolver->setLatestDateTime(end);
209     resolver->findAllFreeSlots();
210 
211     QCOMPARE(resolver->availableSlots().size(), 0);
212 }
213 
testPeriodBeginsBeforeTimeframeBegins()214 void ConflictResolverTest::testPeriodBeginsBeforeTimeframeBegins()
215 {
216     base.setDate(QDate(2010, 7, 29));
217     base.setTime(QTime(7, 30));
218 
219     end.setDate(QDate(2010, 7, 29));
220     end.setTime(QTime(9, 30));
221 
222     KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45));
223 
224     addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"),
225                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent)));
226     addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List())));
227 
228     insertAttendees();
229     resolver->setEarliestDateTime(base);
230     resolver->setLatestDateTime(end);
231     resolver->findAllFreeSlots();
232 
233     QCOMPARE(resolver->availableSlots().size(), 1);
234     KCalendarCore::Period freeslot = resolver->availableSlots().at(0);
235     QCOMPARE(freeslot.start(), _time(8, 45));
236     QCOMPARE(freeslot.end(), end);
237 }
238 
testPeriodEndsAfterTimeframeEnds()239 void ConflictResolverTest::testPeriodEndsAfterTimeframeEnds()
240 {
241     base.setDate(QDate(2010, 7, 29));
242     base.setTime(QTime(7, 30));
243 
244     end.setDate(QDate(2010, 7, 29));
245     end.setTime(QTime(9, 30));
246 
247     KCalendarCore::Period testEvent(_time(8, 00), _time(9, 45));
248 
249     addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"),
250                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent)));
251     addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List())));
252 
253     insertAttendees();
254     resolver->setEarliestDateTime(base);
255     resolver->setLatestDateTime(end);
256     resolver->findAllFreeSlots();
257 
258     QCOMPARE(resolver->availableSlots().size(), 1);
259     KCalendarCore::Period freeslot = resolver->availableSlots().at(0);
260     QCOMPARE(freeslot.duration(), KCalendarCore::Duration(30 * 60));
261     QCOMPARE(freeslot.start(), base);
262     QCOMPARE(freeslot.end(), _time(8, 00));
263 }
264 
testPeriodEndsAtSametimeAsTimeframe()265 void ConflictResolverTest::testPeriodEndsAtSametimeAsTimeframe()
266 {
267     base.setDate(QDate(2010, 7, 29));
268     base.setTime(QTime(7, 45));
269 
270     end.setDate(QDate(2010, 7, 29));
271     end.setTime(QTime(8, 45));
272 
273     KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45));
274 
275     addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"),
276                 KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent)));
277     addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List())));
278 
279     insertAttendees();
280     resolver->setEarliestDateTime(base);
281     resolver->setLatestDateTime(end);
282     resolver->findAllFreeSlots();
283 
284     QCOMPARE(resolver->availableSlots().size(), 0);
285 }
286 
287 QTEST_MAIN(ConflictResolverTest)
288