Merge lp:~charlesk/indicator-datetime/15.04-lp-1473068-sanitize-inputs-to-GTimeZoneNew into lp:indicator-datetime/15.04

Proposed by Charles Kerr on 2015-07-09
Status: Merged
Approved by: Antti Kaijanmäki on 2015-07-09
Approved revision: 425
Merged at revision: 418
Proposed branch: lp:~charlesk/indicator-datetime/15.04-lp-1473068-sanitize-inputs-to-GTimeZoneNew
Merge into: lp:indicator-datetime/15.04
Diff against target: 719 lines (+397/-102)
8 files modified
debian/changelog (+23/-27)
src/engine-eds.cpp (+68/-28)
tests/CMakeLists.txt (+7/-16)
tests/run-eds-ics-test.sh (+30/-31)
tests/test-eds-ics-tzids-2.cpp (+88/-0)
tests/test-eds-ics-tzids-2.ics (+38/-0)
tests/test-eds-ics-tzids.cpp (+87/-0)
tests/test-eds-ics-tzids.ics (+56/-0)
To merge this branch: bzr merge lp:~charlesk/indicator-datetime/15.04-lp-1473068-sanitize-inputs-to-GTimeZoneNew
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve on 2015-07-10
PS Jenkins bot (community) continuous-integration Approve on 2015-07-09
Antti Kaijanmäki (community) Approve on 2015-07-09
dobey (community) 2015-07-09 Approve on 2015-07-09
Review via email: mp+264338@code.launchpad.net

Commit message

Get icaltimezone structures from EDS rather than assuming the tzid will always be GTimeZone friendly.

Description of the change

When we get a tzid from EDS, have EDS convert it into an icaltimezone struct itself, then use =that= to create our own GTimeZones. This way we have a better chance of getting a tzid that GTimeZone will be happy with.

To post a comment you must log in.
421. By Charles Kerr on 2015-07-09

avoid the round trip to EDS if we can figure out the tzid from libical first

422. By Charles Kerr on 2015-07-09

add dobey's test case that has 'TZID:Pacific Time (US & Canada)'

423. By Charles Kerr on 2015-07-09

oops, disabling the other tests was only supposed to be to speed up local tests & wasn't supposed to be pushed

424. By Charles Kerr on 2015-07-09

add dobey's tests

425. By Charles Kerr on 2015-07-09

add a g_warning() if we can't suss out the tzid

dobey (dobey) :
review: Approve
Antti Kaijanmäki (kaijanmaki) wrote :

LGTM.

review: Approve
426. By Charles Kerr on 2015-07-10

sync with trunk

Charles Kerr (charlesk) wrote :

approving trunk sync to make build happy

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2015-06-18 19:25:41 +0000
3+++ debian/changelog 2015-07-10 17:29:43 +0000
4@@ -1,3 +1,26 @@
5+indicator-datetime (13.10.0+15.10.20150624-0ubuntu1) wily; urgency=medium
6+
7+ [ Charles Kerr ]
8+ * Speedups/cleanups to the EDS regression tests
9+
10+ -- CI Train Bot <ci-train-bot@canonical.com> Wed, 24 Jun 2015 12:51:27 +0000
11+
12+indicator-datetime (13.10.0+15.10.20150622-0ubuntu1) wily; urgency=medium
13+
14+ [ Charles Kerr ]
15+ * Fix bugs relating to timezones and triggers from clock-app alarms.
16+ (LP: #1456281, #1465806)
17+
18+ -- CI Train Bot <ci-train-bot@canonical.com> Mon, 22 Jun 2015 18:03:38 +0000
19+
20+indicator-datetime (13.10.0+15.10.20150515-0ubuntu1) wily; urgency=medium
21+
22+ [ Charles Kerr ]
23+ * Honor the 'other vibrations' setting to enable/disable vibrations
24+ when alarm notifications are shown.
25+
26+ -- CI Train Bot <ci-train-bot@canonical.com> Fri, 15 May 2015 16:41:41 +0000
27+
28 indicator-datetime (13.10.0+15.04.20150618-0ubuntu1) vivid; urgency=medium
29
30 [ Charles Kerr ]
31@@ -5,33 +28,6 @@
32
33 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 18 Jun 2015 19:25:41 +0000
34
35-indicator-datetime (13.10.0+15.04.20150521-0ubuntu1) vivid; urgency=medium
36-
37- [ Charles Kerr ]
38- * Fix regression that caused nonrepeating alarms to go off at the
39- wrong time. (LP: #1456281)
40-
41- -- CI Train Bot <ci-train-bot@canonical.com> Thu, 21 May 2015 15:24:31 +0000
42-
43-indicator-datetime (13.10.0+15.04.20150515-0ubuntu1) vivid; urgency=medium
44-
45- [ Charles Kerr ]
46- * Honor the 'other vibrations' setting to enable/disable vibrations
47- when alarm notifications are shown.
48-
49- -- CI Train Bot <ci-train-bot@canonical.com> Fri, 15 May 2015 19:33:54 +0000
50-
51-indicator-datetime (13.10.0+15.04.20150508.2-0ubuntu1) vivid; urgency=medium
52-
53- [ CI Train Bot ]
54- * New rebuild forced.
55-
56- [ Charles Kerr ]
57- * If the "X-CANONICAL-ACTIVATION-URL" x-prop is defined in the VTODO
58- or VEVENT, use it for url delegation. (LP: #1426519)
59-
60- -- CI Train Bot <ci-train-bot@canonical.com> Fri, 08 May 2015 20:01:09 +0000
61-
62 indicator-datetime (13.10.0+15.04.20150406-0ubuntu1) vivid; urgency=medium
63
64 [ Charles Kerr ]
65
66=== modified file 'src/engine-eds.cpp'
67--- src/engine-eds.cpp 2015-06-18 04:53:52 +0000
68+++ src/engine-eds.cpp 2015-07-10 17:29:43 +0000
69@@ -47,16 +47,21 @@
70 {
71 public:
72
73- Impl():
74- m_cancellable(g_cancellable_new())
75+ Impl()
76 {
77- e_source_registry_new(m_cancellable, on_source_registry_ready, this);
78+ auto cancellable_deleter = [](GCancellable * c) {
79+ g_cancellable_cancel(c);
80+ g_clear_object(&c);
81+ };
82+
83+ m_cancellable = std::shared_ptr<GCancellable>(g_cancellable_new(), cancellable_deleter);
84+
85+ e_source_registry_new(m_cancellable.get(), on_source_registry_ready, this);
86 }
87
88 ~Impl()
89 {
90- g_cancellable_cancel(m_cancellable);
91- g_clear_object(&m_cancellable);
92+ m_cancellable.reset();
93
94 while(!m_sources.empty())
95 remove_source(*m_sources.begin());
96@@ -131,9 +136,9 @@
97 e_cal_client_get_object_list_as_comps(
98 client,
99 sexp,
100- m_cancellable,
101+ m_cancellable.get(),
102 on_alarm_component_list_ready,
103- new ClientSubtask(main_task, client, color));
104+ new ClientSubtask(main_task, client, m_cancellable, color));
105 g_clear_pointer(&sexp, g_free);
106
107 // ask EDS about events that occur in this window...
108@@ -142,9 +147,9 @@
109 e_cal_client_get_object_list_as_comps(
110 client,
111 sexp,
112- m_cancellable,
113+ m_cancellable.get(),
114 on_event_component_list_ready,
115- new ClientSubtask(main_task, client, color));
116+ new ClientSubtask(main_task, client, m_cancellable, color));
117 g_clear_pointer(&sexp, g_free);
118
119 g_clear_pointer(&sexp_fmt, g_free);
120@@ -160,7 +165,7 @@
121 e_cal_client_get_object(kv.second,
122 appointment.uid.c_str(),
123 nullptr,
124- m_cancellable,
125+ m_cancellable.get(),
126 on_object_ready_for_disable,
127 this);
128 }
129@@ -271,7 +276,7 @@
130 g_debug("%s connecting a client to source %s", G_STRFUNC, source_uid);
131 e_cal_client_connect(source,
132 source_type,
133- self->m_cancellable,
134+ self->m_cancellable.get(),
135 on_client_connected,
136 gself);
137 }
138@@ -306,7 +311,7 @@
139 // now create a view for it so that we can listen for changes
140 e_cal_client_get_view (ecc,
141 "#t", // match all
142- self->m_cancellable,
143+ self->m_cancellable.get(),
144 on_client_view_ready,
145 self);
146
147@@ -429,7 +434,7 @@
148 e_cal_client_get_object_list_as_comps(
149 client,
150 sexp,
151- m_cancellable,
152+ m_cancellable.get(),
153 ensure_client_alarms_have_triggers_async_cb,
154 this);
155
156@@ -510,7 +515,7 @@
157 e_cal_client_modify_objects(client,
158 modify_slist,
159 E_CAL_OBJ_MOD_ALL,
160- m_cancellable,
161+ m_cancellable.get(),
162 ensure_canonical_alarms_have_triggers_async_cb,
163 this);
164
165@@ -580,13 +585,16 @@
166 {
167 std::shared_ptr<Task> task;
168 ECalClient* client;
169+ std::shared_ptr<GCancellable> cancellable;
170 std::string color;
171
172 ClientSubtask(const std::shared_ptr<Task>& task_in,
173 ECalClient* client_in,
174+ const std::shared_ptr<GCancellable>& cancellable_in,
175 const char* color_in):
176 task(task_in),
177- client(client_in)
178+ client(client_in),
179+ cancellable(cancellable_in)
180 {
181 if (color_in)
182 color = color_in;
183@@ -720,15 +728,44 @@
184 }
185
186 static DateTime
187- datetime_from_component_date_time(const ECalComponentDateTime & in,
188- GTimeZone * default_timezone)
189+ datetime_from_component_date_time(ECalClient * client,
190+ std::shared_ptr<GCancellable> & cancellable,
191+ const ECalComponentDateTime & in,
192+ GTimeZone * default_timezone)
193 {
194 DateTime out;
195-
196 g_return_val_if_fail(in.value != nullptr, out);
197
198- auto gtz = in.tzid == nullptr ? g_time_zone_ref(default_timezone)
199- : g_time_zone_new(in.tzid);
200+ GTimeZone * gtz {};
201+ if (in.tzid != nullptr)
202+ {
203+ auto itz = icaltimezone_get_builtin_timezone_from_tzid(in.tzid); // usually works
204+
205+ if (itz == nullptr) // fallback
206+ itz = icaltimezone_get_builtin_timezone(in.tzid);
207+
208+ if (itz == nullptr) // ok we have a strange tzid... ask EDS to look it up in VTIMEZONES
209+ e_cal_client_get_timezone_sync(client, in.tzid, &itz, cancellable.get(), nullptr);
210+
211+ const char * tzid;
212+ if (itz != nullptr)
213+ {
214+ tzid = icaltimezone_get_location(itz);
215+ }
216+ else
217+ {
218+ g_warning("Unrecognized TZID: '%s'", in.tzid);
219+ tzid = nullptr;
220+ }
221+
222+ gtz = g_time_zone_new(tzid);
223+ g_debug("%s eccdt.tzid -> offset is %d", G_STRLOC, in.tzid, (int)g_time_zone_get_offset(gtz,0));
224+ }
225+ else
226+ {
227+ gtz = g_time_zone_ref(default_timezone);
228+ }
229+
230 out = DateTime(gtz,
231 in.value->year,
232 in.value->month,
233@@ -773,7 +810,10 @@
234 }
235
236 static Appointment
237- get_appointment(ECalComponent * component, GTimeZone * gtz)
238+ get_appointment(ECalClient * client,
239+ std::shared_ptr<GCancellable> & cancellable,
240+ ECalComponent * component,
241+ GTimeZone * gtz)
242 {
243 Appointment baseline;
244
245@@ -792,13 +832,13 @@
246 // get appointment.begin
247 ECalComponentDateTime eccdt_tmp {};
248 e_cal_component_get_dtstart(component, &eccdt_tmp);
249- baseline.begin = datetime_from_component_date_time(eccdt_tmp, gtz);
250+ baseline.begin = datetime_from_component_date_time(client, cancellable, eccdt_tmp, gtz);
251 e_cal_component_free_datetime(&eccdt_tmp);
252
253 // get appointment.end
254 e_cal_component_get_dtend(component, &eccdt_tmp);
255 baseline.end = eccdt_tmp.value != nullptr
256- ? datetime_from_component_date_time(eccdt_tmp, gtz)
257+ ? datetime_from_component_date_time(client, cancellable, eccdt_tmp, gtz)
258 : baseline.begin;
259 e_cal_component_free_datetime(&eccdt_tmp);
260
261@@ -839,7 +879,7 @@
262 ClientSubtask * subtask,
263 GTimeZone * gtz)
264 {
265- // events with alarms are covered by add_alarm_to_subtask(),
266+ // events with alarms are covered by add_alarms_to_subtask(),
267 // so skip them here
268 auto auids = e_cal_component_get_alarm_uids(component);
269 const bool has_alarms = auids != nullptr;
270@@ -850,7 +890,7 @@
271 // add it. simple, eh?
272 if (is_component_interesting(component))
273 {
274- Appointment appointment = get_appointment(component, gtz);
275+ Appointment appointment = get_appointment(subtask->client, subtask->cancellable, component, gtz);
276 appointment.color = subtask->color;
277 subtask->task->appointments.push_back(appointment);
278 }
279@@ -866,7 +906,7 @@
280 if (!is_component_interesting(component))
281 return;
282
283- Appointment baseline = get_appointment(component, gtz);
284+ Appointment baseline = get_appointment(subtask->client, subtask->cancellable, component, gtz);
285 baseline.color = subtask->color;
286
287 /**
288@@ -958,7 +998,7 @@
289 e_cal_client_modify_object(E_CAL_CLIENT(client),
290 e_cal_component_get_icalcomponent(ecc),
291 E_CAL_OBJ_MOD_THIS,
292- static_cast<Impl*>(gself)->m_cancellable,
293+ static_cast<Impl*>(gself)->m_cancellable.get(),
294 on_disable_done,
295 nullptr);
296
297@@ -990,7 +1030,7 @@
298 std::set<ESource*> m_sources;
299 std::map<ESource*,ECalClient*> m_clients;
300 std::map<ESource*,ECalClientView*> m_views;
301- GCancellable* m_cancellable {};
302+ std::shared_ptr<GCancellable> m_cancellable;
303 ESourceRegistry* m_source_registry {};
304 guint m_rebuild_tag {};
305 time_t m_rebuild_deadline {};
306
307=== modified file 'tests/CMakeLists.txt'
308--- tests/CMakeLists.txt 2015-06-18 04:52:52 +0000
309+++ tests/CMakeLists.txt 2015-07-10 17:29:43 +0000
310@@ -70,13 +70,6 @@
311 ##
312
313 find_program(DBUS_RUNNER dbus-test-runner)
314-find_program(EVOLUTION_CALENDAR_FACTORY evolution-calendar-factory PATHS /usr/lib/evolution/)
315-find_program(EVOLUTION_SOURCE_REGISTRY evolution-source-registry PATHS /usr/lib/evolution/)
316-find_program(GVFSD gvfsd PATHS /usr/lib/gvfs/)
317-OPTION(EVOLUTION_SOURCE_SERVICE_NAME "DBus name for source registry")
318-if(NOT EVOLUTION_SOURCE_SERVICE_NAME)
319- set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources3")
320-endif()
321
322 function(add_eds_ics_test_by_name name)
323 set (TEST_NAME ${name})
324@@ -84,21 +77,19 @@
325 target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
326 add_test (${TEST_NAME}
327 ${CMAKE_CURRENT_SOURCE_DIR}/run-eds-ics-test.sh
328- ${DBUS_RUNNER} # arg1: dbus-test-runner exec
329- ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
330- ${TEST_NAME} # arg3: test name
331- ${EVOLUTION_CALENDAR_FACTORY} # arg4: evolution-calendar-factory exec
332- ${EVOLUTION_SOURCE_SERVICE_NAME} # arg5: dbus name for source registry
333- ${EVOLUTION_SOURCE_REGISTRY} # arg6: evolution-source-registry exec
334- ${GVFSD} # arg7: gvfsd exec
335- ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg8: base directory for config file template
336- ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.ics) # arg9: the ical file for this test
337+ ${DBUS_RUNNER} # arg1: dbus-test-runner exec
338+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
339+ ${TEST_NAME} # arg3: test name
340+ ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template
341+ ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.ics) # arg5: the ical file for this test
342 endfunction()
343 add_eds_ics_test_by_name(test-eds-ics-all-day-events)
344 add_eds_ics_test_by_name(test-eds-ics-repeating-events)
345 add_eds_ics_test_by_name(test-eds-ics-nonrepeating-events)
346 add_eds_ics_test_by_name(test-eds-ics-repeating-valarms)
347 add_eds_ics_test_by_name(test-eds-ics-missing-trigger)
348+add_eds_ics_test_by_name(test-eds-ics-tzids)
349+add_eds_ics_test_by_name(test-eds-ics-tzids-2)
350
351
352 # disabling the timezone unit tests because they require
353
354=== modified file 'tests/run-eds-ics-test.sh'
355--- tests/run-eds-ics-test.sh 2015-05-21 11:09:52 +0000
356+++ tests/run-eds-ics-test.sh 2015-07-10 17:29:43 +0000
357@@ -1,19 +1,22 @@
358 #!/bin/sh
359
360-echo ARG0=$0 # this script
361-echo ARG1=$1 # full executable path of dbus-test-runner
362-echo ARG2=$2 # full executable path of test app
363-echo ARG3=$3 # test name
364-echo ARG4=$4 # full executable path of evolution-calendar-factory
365-echo ARG5=$5 # bus service name of calendar factory
366-echo ARG6=$6 # full exectuable path of evolution-source-registry
367-echo ARG7=$7 # full executable path of gvfs
368-echo ARG8=$8 # config files
369-echo ARG8=$9 # ics file
370-
371-# set up the tmpdir and tell the shell to purge it when we exit
372-export TEST_TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d $3-XXXXXXXXXX) || exit 1
373-echo "running test '$3' in ${TEST_TMP_DIR}"
374+SELF=$0 # this script
375+TEST_RUNNER=$1 # full executable path of dbus-test-runner
376+TEST_EXEC=$2 # full executable path of test app
377+TEST_NAME=$3 # test name
378+CONFIG_DIR=$4 # config files
379+ICS_FILE=$5 # ical file holding test data
380+
381+echo "this script: ${SELF}"
382+echo "test-runner: ${TEST_RUNNER}"
383+echo "test-exec: ${TEST_EXEC}"
384+echo "test-name: ${TEST_NAME}"
385+echo "config-dir: ${CONFIG_DIR}"
386+echo "ics-file: ${ICS_FILE}"
387+
388+# set up the tmpdir
389+export TEST_TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d ${TEST_NAME}-XXXXXXXXXX) || exit 1
390+echo "running test '${TEST_NAME}' in ${TEST_TMP_DIR}"
391
392 # set up the environment variables
393 export QT_QPA_PLATFORM=minimal
394@@ -40,23 +43,19 @@
395 rm -rf ${XDG_DATA_HOME}
396
397 # if there are canned config files for this test, move them into place now
398-if [ -d $8 ]; then
399- echo "copying files from $8 to $HOME"
400- cp --verbose --archive $8/. $HOME
401-fi
402-
403-# if there's a specific ics file to test, copy it on top of the canned confilg files
404-if [ -e $9 ]; then
405- echo "copying $9 into $HOME"
406- cp --verbose --archive $9 ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
407-fi
408-
409-# run dbus-test-runner
410-$1 --keep-env --max-wait=90 \
411---task $2 --task-name $3 --wait-until-complete --wait-for=org.gnome.evolution.dataserver.Calendar4 \
412---task $4 --task-name "evolution" --wait-until-complete -r
413-#--task $6 --task-name "source-registry" --wait-for=org.gtk.vfs.Daemon -r \
414-#--task $7 --task-name "gvfsd" -r
415+if [ -d ${CONFIG_DIR} ]; then
416+ echo "copying files from ${CONFIG_DIR} to $HOME"
417+ cp --verbose --archive ${CONFIG_DIR}/. $HOME
418+fi
419+
420+# if there's a specific ics file to test, copy it on top of the canned config files
421+if [ -e ${ICS_FILE} ]; then
422+ echo "copying ${ICS_FILE} into $HOME"
423+ cp --verbose --archive ${ICS_FILE} ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
424+fi
425+
426+# run the test
427+${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete
428 rv=$?
429
430 # if the test passed, blow away the tmpdir
431
432=== added file 'tests/test-eds-ics-tzids-2.cpp'
433--- tests/test-eds-ics-tzids-2.cpp 1970-01-01 00:00:00 +0000
434+++ tests/test-eds-ics-tzids-2.cpp 2015-07-10 17:29:43 +0000
435@@ -0,0 +1,88 @@
436+/*
437+ * Copyright 2015 Canonical Ltd.
438+ *
439+ * This program is free software: you can redistribute it and/or modify it
440+ * under the terms of the GNU General Public License version 3, as published
441+ * by the Free Software Foundation.
442+ *
443+ * This program is distributed in the hope that it will be useful, but
444+ * WITHOUT ANY WARRANTY; without even the implied warranties of
445+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
446+ * PURPOSE. See the GNU General Public License for more details.
447+ *
448+ * You should have received a copy of the GNU General Public License along
449+ * with this program. If not, see <http://www.gnu.org/licenses/>.
450+ *
451+ * Authors:
452+ * Charles Kerr <charles.kerr@canonical.com>
453+ */
454+
455+#include <algorithm>
456+
457+#include <datetime/alarm-queue-simple.h>
458+#include <datetime/clock-mock.h>
459+#include <datetime/engine-eds.h>
460+#include <datetime/planner-range.h>
461+
462+#include <gtest/gtest.h>
463+
464+#include "glib-fixture.h"
465+#include "print-to.h"
466+#include "timezone-mock.h"
467+#include "wakeup-timer-mock.h"
468+
469+using namespace unity::indicator::datetime;
470+using VAlarmFixture = GlibFixture;
471+
472+/***
473+****
474+***/
475+
476+TEST_F(VAlarmFixture, MultipleAppointments)
477+{
478+ // start the EDS engine
479+ auto engine = std::make_shared<EdsEngine>();
480+
481+ // we need a consistent timezone for the planner and our local DateTimes
482+ constexpr char const * zone_str {"America/Los_Angeles"};
483+ auto tz = std::make_shared<MockTimezone>(zone_str);
484+ auto gtz = g_time_zone_new(zone_str);
485+
486+ // make a planner that looks at the first half of 2015 in EDS
487+ auto planner = std::make_shared<SimpleRangePlanner>(engine, tz);
488+ const DateTime range_begin {gtz, 2006,1, 1, 0, 0, 0.0};
489+ const DateTime range_end {gtz, 2015,12,31,23,59,59.5};
490+ planner->range().set(std::make_pair(range_begin, range_end));
491+
492+ // give EDS a moment to load
493+ if (planner->appointments().get().empty()) {
494+ g_message("waiting a moment for EDS to load...");
495+ auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){
496+ g_message("ah, they loaded");
497+ if (!appointments.empty())
498+ g_main_loop_quit(loop);
499+ };
500+ core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed));
501+ constexpr int max_wait_sec = 10;
502+ wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
503+ }
504+
505+ // what we expect to get...
506+ std::array<Appointment,1> expected_appts;
507+ auto appt = &expected_appts[0];
508+ appt->uid = "109264742";
509+ appt->color = "#becedd";
510+ appt->summary = "National Incubator Initiative for Clean Energy (NIICE) FOA: Pre-Concept Paper Informational Webinar";
511+ appt->begin = DateTime{gtz,2014,1,21,11,0,0};
512+ appt->end = DateTime{gtz,2014,1,21,13,0,0};
513+ appt->alarms = std::vector<Alarm>{ Alarm({"Reminder", "", DateTime(gtz,2014,1,21,10,45,0)}) };
514+
515+ // compare it to what we actually loaded...
516+ const auto appts = planner->appointments().get();
517+ EXPECT_EQ(expected_appts.size(), appts.size());
518+ for (size_t i=0, n=std::min(appts.size(),expected_appts.size()); i<n; i++)
519+ EXPECT_EQ(expected_appts[i], appts[i]);
520+
521+ // cleanup
522+ g_time_zone_unref(gtz);
523+}
524
525=== added file 'tests/test-eds-ics-tzids-2.ics'
526--- tests/test-eds-ics-tzids-2.ics 1970-01-01 00:00:00 +0000
527+++ tests/test-eds-ics-tzids-2.ics 2015-07-10 17:29:43 +0000
528@@ -0,0 +1,38 @@
529+BEGIN:VCALENDAR
530+CALSCALE:GREGORIAN
531+PRODID:-//Ximian//NONSGML Evolution Calendar//EN
532+VERSION:2.0
533+X-EVOLUTION-DATA-REVISION:2015-07-09T19:41:50.123217Z(3)
534+BEGIN:VTIMEZONE
535+TZID:Pacific Time (US & Canada)
536+BEGIN:STANDARD
537+DTSTART:20061105T020000
538+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
539+TZOFFSETFROM:-0700
540+TZOFFSETTO:-0800
541+END:STANDARD
542+BEGIN:DAYLIGHT
543+DTSTART:20070311T020000
544+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
545+TZOFFSETFROM:-0800
546+TZOFFSETTO:-0700
547+TZNAME:Daylight Savings Time
548+END:DAYLIGHT
549+END:VTIMEZONE
550+BEGIN:VEVENT
551+DTSTART;TZID=Pacific Time (US & Canada):20140121T110000
552+DTEND;TZID=Pacific Time (US & Canada):20140121T130000
553+UID:109264742
554+DTSTAMP:20140120T000718Z
555+DESCRIPTION: Event description
556+SUMMARY;ENCODING=QUOTED-PRINTABLE:National Incubator Initiative for Clean
557+ Energy (NIICE) FOA: Pre-Concept Paper Informational Webinar
558+CREATED:20140120T000741Z
559+LAST-MODIFIED:20140120T000741Z
560+BEGIN:VALARM
561+TRIGGER;VALUE=DURATION:-PT15M
562+ACTION:DISPLAY
563+DESCRIPTION:Reminder
564+END:VALARM
565+END:VEVENT
566+END:VCALENDAR
567
568=== added file 'tests/test-eds-ics-tzids.cpp'
569--- tests/test-eds-ics-tzids.cpp 1970-01-01 00:00:00 +0000
570+++ tests/test-eds-ics-tzids.cpp 2015-07-10 17:29:43 +0000
571@@ -0,0 +1,87 @@
572+/*
573+ * Copyright 2015 Canonical Ltd.
574+ *
575+ * This program is free software: you can redistribute it and/or modify it
576+ * under the terms of the GNU General Public License version 3, as published
577+ * by the Free Software Foundation.
578+ *
579+ * This program is distributed in the hope that it will be useful, but
580+ * WITHOUT ANY WARRANTY; without even the implied warranties of
581+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
582+ * PURPOSE. See the GNU General Public License for more details.
583+ *
584+ * You should have received a copy of the GNU General Public License along
585+ * with this program. If not, see <http://www.gnu.org/licenses/>.
586+ *
587+ * Authors:
588+ * Charles Kerr <charles.kerr@canonical.com>
589+ */
590+
591+#include <algorithm>
592+
593+#include <datetime/alarm-queue-simple.h>
594+#include <datetime/clock-mock.h>
595+#include <datetime/engine-eds.h>
596+#include <datetime/planner-range.h>
597+
598+#include <gtest/gtest.h>
599+
600+#include "glib-fixture.h"
601+#include "print-to.h"
602+#include "timezone-mock.h"
603+#include "wakeup-timer-mock.h"
604+
605+using namespace unity::indicator::datetime;
606+using VAlarmFixture = GlibFixture;
607+
608+/***
609+****
610+***/
611+
612+TEST_F(VAlarmFixture, MultipleAppointments)
613+{
614+ // start the EDS engine
615+ auto engine = std::make_shared<EdsEngine>();
616+
617+ // we need a consistent timezone for the planner and our local DateTimes
618+ constexpr char const * zone_str {"Europe/Berlin"};
619+ auto tz = std::make_shared<MockTimezone>(zone_str);
620+ auto gtz = g_time_zone_new(zone_str);
621+
622+ // make a planner that looks at the first half of 2015 in EDS
623+ auto planner = std::make_shared<SimpleRangePlanner>(engine, tz);
624+ const DateTime range_begin {gtz, 2015,7, 1, 0, 0, 0.0};
625+ const DateTime range_end {gtz, 2015,7,31,23,59,59.5};
626+ planner->range().set(std::make_pair(range_begin, range_end));
627+
628+ // give EDS a moment to load
629+ if (planner->appointments().get().empty()) {
630+ g_message("waiting a moment for EDS to load...");
631+ auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){
632+ g_message("ah, they loaded");
633+ if (!appointments.empty())
634+ g_main_loop_quit(loop);
635+ };
636+ core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed));
637+ constexpr int max_wait_sec = 10;
638+ wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
639+ }
640+
641+ // what we expect to get...
642+ std::array<Appointment,1> expected_appts;
643+ auto appt = &expected_appts[0];
644+ appt->uid = "8ggc30kh89qql8vjumgtug7l14@google.com";
645+ appt->color = "#becedd";
646+ appt->summary = "Hello";
647+ appt->begin = DateTime{gtz,2015,7,1,20,0,0};
648+ appt->end = DateTime{gtz,2015,7,1,22,0,0};
649+
650+ // compare it to what we actually loaded...
651+ const auto appts = planner->appointments().get();
652+ EXPECT_EQ(expected_appts.size(), appts.size());
653+ for (size_t i=0, n=std::min(appts.size(),expected_appts.size()); i<n; i++)
654+ EXPECT_EQ(expected_appts[i], appts[i]);
655+
656+ // cleanup
657+ g_time_zone_unref(gtz);
658+}
659
660=== added file 'tests/test-eds-ics-tzids.ics'
661--- tests/test-eds-ics-tzids.ics 1970-01-01 00:00:00 +0000
662+++ tests/test-eds-ics-tzids.ics 2015-07-10 17:29:43 +0000
663@@ -0,0 +1,56 @@
664+BEGIN:VCALENDAR
665+CALSCALE:GREGORIAN
666+PRODID:-//Ximian//NONSGML Evolution Calendar//EN
667+VERSION:2.0
668+X-EVOLUTION-DATA-REVISION:2015-07-09T17:27:58.908570Z(0)
669+BEGIN:VTIMEZONE
670+TZID:/freeassociation.sourceforge.net/Tzfile/America/Sao_Paulo
671+X-LIC-LOCATION:America/Sao_Paulo
672+BEGIN:STANDARD
673+TZNAME:BRT
674+DTSTART:19700222T000000
675+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=2
676+TZOFFSETFROM:-0200
677+TZOFFSETTO:-0300
678+END:STANDARD
679+BEGIN:DAYLIGHT
680+TZNAME:BRST
681+DTSTART:19701018T000000
682+RRULE:FREQ=YEARLY;BYDAY=3SU;BYMONTH=10
683+TZOFFSETFROM:-0300
684+TZOFFSETTO:-0200
685+END:DAYLIGHT
686+END:VTIMEZONE
687+BEGIN:VTIMEZONE
688+TZID:/freeassociation.sourceforge.net/Tzfile/Europe/Berlin
689+X-LIC-LOCATION:Europe/Berlin
690+BEGIN:STANDARD
691+TZNAME:CET
692+DTSTART:19701025T030000
693+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
694+TZOFFSETFROM:+0200
695+TZOFFSETTO:+0100
696+END:STANDARD
697+BEGIN:DAYLIGHT
698+TZNAME:CEST
699+DTSTART:19700329T020000
700+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
701+TZOFFSETFROM:+0100
702+TZOFFSETTO:+0200
703+END:DAYLIGHT
704+END:VTIMEZONE
705+BEGIN:VEVENT
706+STATUS:CONFIRMED
707+DTSTAMP:20150708T095820Z
708+CREATED:20150708T095820Z
709+UID:8ggc30kh89qql8vjumgtug7l14@google.com
710+SEQUENCE:0
711+TRANSP:OPAQUE
712+SUMMARY:Hello
713+DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Berlin:
714+ 20150701T200000
715+DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Berlin:
716+ 20150701T220000
717+LAST-MODIFIED:20150708T095820Z
718+END:VEVENT
719+END:VCALENDAR

Subscribers

People subscribed via source and target branches