Merge lp:~charlesk/indicator-datetime/lp-1456281-fix-15.04-alarm-regression into lp:indicator-datetime/15.04
- lp-1456281-fix-15.04-alarm-regression
- Merge into trunk.15.04
Status: | Merged |
---|---|
Approved by: | Ted Gould |
Approved revision: | 428 |
Merged at revision: | 414 |
Proposed branch: | lp:~charlesk/indicator-datetime/lp-1456281-fix-15.04-alarm-regression |
Merge into: | lp:indicator-datetime/15.04 |
Diff against target: |
1442 lines (+809/-433) 17 files modified
src/engine-eds.cpp (+348/-200) tests/CMakeLists.txt (+15/-14) tests/print-to.h (+10/-1) tests/run-eds-ics-test.sh (+10/-0) tests/test-eds-ics-all-day-events.cpp (+91/-0) tests/test-eds-ics-all-day-events.ics (+19/-0) tests/test-eds-ics-config-files/.config/evolution/sources/system-proxy.source (+21/-0) tests/test-eds-ics-nonrepeating-events.cpp (+93/-0) tests/test-eds-ics-nonrepeating-events.ics (+27/-0) tests/test-eds-ics-repeating-events.cpp (+100/-0) tests/test-eds-ics-repeating-events.ics (+28/-0) tests/test-eds-ics-repeating-valarms.ics (+47/-0) tests/test-eds-tasks-config-files/.config/evolution/sources/system-proxy.source (+0/-21) tests/test-eds-tasks-config-files/.local/share/evolution/tasks/system/tasks.ics (+0/-28) tests/test-eds-tasks.cpp (+0/-101) tests/test-eds-valarms-config-files/.config/evolution/sources/system-proxy.source (+0/-21) tests/test-eds-valarms-config-files/.local/share/evolution/calendar/system/calendar.ics (+0/-47) |
To merge this branch: | bzr merge lp:~charlesk/indicator-datetime/lp-1456281-fix-15.04-alarm-regression |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+259713@code.launchpad.net |
Commit message
Fix regression that caused nonrepeating alarms to go off at the wrong time.
Description of the change
== Description of the Change
So, for the purposes of this description there are two kinds of ECalComponents: the primary one for an event, and instance components that are what you get when you have a repeating event.
Timezones for "floating" times (e.g., an alarm that goes off at 6:30 AM regardless of the current timezone) get distorted when you call e_cal_util_
So, the old code flow was
for (instance : e_cal_client_
for (alarm : e_cal_util_
The new flow is:
for (component : e_cal_client_
for (alarm : e_cal_util_
...if only the actual code were that easy :-)
Also, ensure EDS regression tests exist for both repeating and nonrepeating alarms.
== Checklist
> Are there any related MPs required for this MP to build/function as expected? Please list.
No
> Is your branch in sync with latest trunk? (e.g. bzr pull lp:trunk -> no changes)
In sync with indicator-
> Did the code build without warnings?
Yes
> Did the tests run successfully?
Yes
> Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
> If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
> What device (or emulator) has your component test plan been executed successfully on?
krillin ubuntu-
> What manual tests are relevant for this MP?
indicator-
> Did you include a link to the MR Review Checklist Template to make your reviewer's life easier?
https:/
- 424. By Charles Kerr
-
remove a little more leftover code from the false starts
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:424
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 425. By Charles Kerr
-
in engine-eds.cpp's get_appointments(), clear the begin_str and end_str variables as soon as we're done with them.
- 426. By Charles Kerr
-
in engine-eds.cpp's on_object_
list_ready( ), always mark the subtask as finished even if the dbus call failed. - 427. By Charles Kerr
-
in run-eds-
ics-test. sh, slightly cleaner ics file copying - 428. By Charles Kerr
-
in eds-engine, add a occur-in-time-range sexp to handle events that are interesting but don't require user notification alarms
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:427
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
Looks like good updates. I really like moving the deleter function into the class, makes it way more readable and easier to track the memory.
Preview Diff
1 | === modified file 'src/engine-eds.cpp' |
2 | --- src/engine-eds.cpp 2015-05-08 00:10:37 +0000 |
3 | +++ src/engine-eds.cpp 2015-05-21 12:47:48 +0000 |
4 | @@ -79,9 +79,6 @@ |
5 | const Timezone& timezone, |
6 | std::function<void(const std::vector<Appointment>&)> func) |
7 | { |
8 | - const auto begin_timet = begin.to_unix(); |
9 | - const auto end_timet = end.to_unix(); |
10 | - |
11 | const auto b_str = begin.format("%F %T"); |
12 | const auto e_str = end.format("%F %T"); |
13 | g_debug("getting all appointments from [%s ... %s]", b_str.c_str(), e_str.c_str()); |
14 | @@ -106,42 +103,51 @@ |
15 | *** walk through the sources to build the appointment list |
16 | **/ |
17 | |
18 | - auto task_deleter = [](Task* task){ |
19 | - // give the caller the (sorted) finished product |
20 | - auto& a = task->appointments; |
21 | - std::sort(a.begin(), a.end(), [](const Appointment& a, const Appointment& b){return a.begin < b.begin;}); |
22 | - task->func(a); |
23 | - // we're done; delete the task |
24 | - g_debug("time to delete task %p", (void*)task); |
25 | - delete task; |
26 | - }; |
27 | - |
28 | - std::shared_ptr<Task> main_task(new Task(this, func), task_deleter); |
29 | + auto gtz = default_timezone != nullptr |
30 | + ? g_time_zone_new(icaltimezone_get_location(default_timezone)) |
31 | + : g_time_zone_new_local(); |
32 | + auto main_task = std::make_shared<Task>(this, func, default_timezone, gtz, begin, end); |
33 | |
34 | for (auto& kv : m_clients) |
35 | { |
36 | auto& client = kv.second; |
37 | if (default_timezone != nullptr) |
38 | e_cal_client_set_default_timezone(client, default_timezone); |
39 | + g_debug("calling e_cal_client_generate_instances for %p", (void*)client); |
40 | |
41 | - // start a new subtask to enumerate all the components in this client. |
42 | auto& source = kv.first; |
43 | auto extension = e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR); |
44 | const auto color = e_source_selectable_get_color(E_SOURCE_SELECTABLE(extension)); |
45 | - g_debug("calling e_cal_client_generate_instances for %p", (void*)client); |
46 | - auto subtask = new AppointmentSubtask(main_task, |
47 | - client, |
48 | - color, |
49 | - default_timezone, |
50 | - begin_timet, |
51 | - end_timet); |
52 | - e_cal_client_generate_instances(client, |
53 | - begin_timet, |
54 | - end_timet, |
55 | - m_cancellable, |
56 | - my_get_appointments_foreach, |
57 | - subtask, |
58 | - [](gpointer g){delete static_cast<AppointmentSubtask*>(g);}); |
59 | + |
60 | + auto begin_str = isodate_from_time_t(begin.to_unix()); |
61 | + auto end_str = isodate_from_time_t(end.to_unix()); |
62 | + auto sexp_fmt = g_strdup_printf("(%%s? (make-time \"%s\") (make-time \"%s\"))", begin_str, end_str); |
63 | + g_clear_pointer(&begin_str, g_free); |
64 | + g_clear_pointer(&end_str, g_free); |
65 | + |
66 | + // ask EDS about alarms that occur in this window... |
67 | + auto sexp = g_strdup_printf(sexp_fmt, "has-alarms-in-range"); |
68 | + g_debug("%s alarm sexp is %s", G_STRLOC, sexp); |
69 | + e_cal_client_get_object_list_as_comps( |
70 | + client, |
71 | + sexp, |
72 | + m_cancellable, |
73 | + on_alarm_component_list_ready, |
74 | + new ClientSubtask(main_task, client, color)); |
75 | + g_clear_pointer(&sexp, g_free); |
76 | + |
77 | + // ask EDS about events that occur in this window... |
78 | + sexp = g_strdup_printf(sexp_fmt, "occur-in-time-range"); |
79 | + g_debug("%s event sexp is %s", G_STRLOC, sexp); |
80 | + e_cal_client_get_object_list_as_comps( |
81 | + client, |
82 | + sexp, |
83 | + m_cancellable, |
84 | + on_event_component_list_ready, |
85 | + new ClientSubtask(main_task, client, color)); |
86 | + g_clear_pointer(&sexp, g_free); |
87 | + |
88 | + g_clear_pointer(&sexp_fmt, g_free); |
89 | } |
90 | } |
91 | |
92 | @@ -409,30 +415,45 @@ |
93 | { |
94 | Impl* p; |
95 | appointment_func func; |
96 | + icaltimezone* default_timezone; // pointer owned by libical |
97 | + GTimeZone* gtz; |
98 | std::vector<Appointment> appointments; |
99 | - Task(Impl* p_in, const appointment_func& func_in): p(p_in), func(func_in) {} |
100 | + const DateTime begin; |
101 | + const DateTime end; |
102 | + |
103 | + Task(Impl* p_in, |
104 | + appointment_func func_in, |
105 | + icaltimezone* tz_in, |
106 | + GTimeZone* gtz_in, |
107 | + const DateTime& begin_in, |
108 | + const DateTime& end_in): |
109 | + p{p_in}, |
110 | + func{func_in}, |
111 | + default_timezone{tz_in}, |
112 | + gtz{gtz_in}, |
113 | + begin{begin_in}, |
114 | + end{end_in} {} |
115 | + |
116 | + ~Task() { |
117 | + g_clear_pointer(>z, g_time_zone_unref); |
118 | + // give the caller the sorted finished product |
119 | + auto& a = appointments; |
120 | + std::sort(a.begin(), a.end(), [](const Appointment& a, const Appointment& b){return a.begin < b.begin;}); |
121 | + func(a); |
122 | + }; |
123 | }; |
124 | |
125 | - struct AppointmentSubtask |
126 | + struct ClientSubtask |
127 | { |
128 | std::shared_ptr<Task> task; |
129 | ECalClient* client; |
130 | std::string color; |
131 | - icaltimezone* default_timezone; |
132 | - time_t begin; |
133 | - time_t end; |
134 | |
135 | - AppointmentSubtask(const std::shared_ptr<Task>& task_in, |
136 | - ECalClient* client_in, |
137 | - const char* color_in, |
138 | - icaltimezone* default_tz, |
139 | - time_t begin_, |
140 | - time_t end_): |
141 | + ClientSubtask(const std::shared_ptr<Task>& task_in, |
142 | + ECalClient* client_in, |
143 | + const char* color_in): |
144 | task(task_in), |
145 | - client(client_in), |
146 | - default_timezone(default_tz), |
147 | - begin(begin_), |
148 | - end(end_) |
149 | + client(client_in) |
150 | { |
151 | if (color_in) |
152 | color = color_in; |
153 | @@ -482,163 +503,290 @@ |
154 | return ret; |
155 | } |
156 | |
157 | - static gboolean |
158 | - my_get_appointments_foreach(ECalComponent* component, |
159 | - time_t begin, |
160 | - time_t end, |
161 | - gpointer gsubtask) |
162 | - { |
163 | + static void |
164 | + on_alarm_component_list_ready(GObject * oclient, |
165 | + GAsyncResult * res, |
166 | + gpointer gsubtask) |
167 | + { |
168 | + GError * error = NULL; |
169 | + GSList * comps_slist = NULL; |
170 | + auto subtask = static_cast<ClientSubtask*>(gsubtask); |
171 | + |
172 | + if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient), |
173 | + res, |
174 | + &comps_slist, |
175 | + &error)) |
176 | + { |
177 | + // _generate_alarms takes a GList, so make a shallow one |
178 | + GList * comps_list = nullptr; |
179 | + for (auto l=comps_slist; l!=nullptr; l=l->next) |
180 | + comps_list = g_list_prepend(comps_list, l->data); |
181 | + |
182 | + constexpr std::array<ECalComponentAlarmAction,1> omit = { |
183 | + (ECalComponentAlarmAction)-1 |
184 | + }; // list of action types to omit, terminated with -1 |
185 | + GSList * comp_alarms = nullptr; |
186 | + e_cal_util_generate_alarms_for_list( |
187 | + comps_list, |
188 | + subtask->task->begin.to_unix(), |
189 | + subtask->task->end.to_unix(), |
190 | + const_cast<ECalComponentAlarmAction*>(omit.data()), |
191 | + &comp_alarms, |
192 | + e_cal_client_resolve_tzid_cb, |
193 | + oclient, |
194 | + subtask->task->default_timezone); |
195 | + |
196 | + // walk the alarms & add them |
197 | + for (auto l=comp_alarms; l!=nullptr; l=l->next) |
198 | + add_alarms_to_subtask(static_cast<ECalComponentAlarms*>(l->data), subtask, subtask->task->gtz); |
199 | + |
200 | + // cleanup |
201 | + e_cal_free_alarms(comp_alarms); |
202 | + g_list_free(comps_list); |
203 | + e_cal_client_free_ecalcomp_slist(comps_slist); |
204 | + } |
205 | + else if (error != nullptr) |
206 | + { |
207 | + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
208 | + g_warning("can't get ecalcomponent list: %s", error->message); |
209 | + |
210 | + g_error_free(error); |
211 | + } |
212 | + |
213 | + delete subtask; |
214 | + } |
215 | + |
216 | + static void |
217 | + on_event_component_list_ready(GObject * oclient, |
218 | + GAsyncResult * res, |
219 | + gpointer gsubtask) |
220 | + { |
221 | + GError * error = NULL; |
222 | + GSList * comps_slist = NULL; |
223 | + auto subtask = static_cast<ClientSubtask*>(gsubtask); |
224 | + |
225 | + if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient), |
226 | + res, |
227 | + &comps_slist, |
228 | + &error)) |
229 | + { |
230 | + for (auto l=comps_slist; l!=nullptr; l=l->next) |
231 | + add_event_to_subtask(static_cast<ECalComponent*>(l->data), subtask, subtask->task->gtz); |
232 | + |
233 | + e_cal_client_free_ecalcomp_slist(comps_slist); |
234 | + } |
235 | + else if (error != nullptr) |
236 | + { |
237 | + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
238 | + g_warning("can't get ecalcomponent list: %s", error->message); |
239 | + |
240 | + g_error_free(error); |
241 | + } |
242 | + |
243 | + delete subtask; |
244 | + } |
245 | + |
246 | + static DateTime |
247 | + datetime_from_component_date_time(const ECalComponentDateTime & in, |
248 | + GTimeZone * default_timezone) |
249 | + { |
250 | + DateTime out; |
251 | + |
252 | + g_return_val_if_fail(in.value != nullptr, out); |
253 | + |
254 | + auto gtz = in.tzid == nullptr ? g_time_zone_ref(default_timezone) |
255 | + : g_time_zone_new(in.tzid); |
256 | + out = DateTime(gtz, |
257 | + in.value->year, |
258 | + in.value->month, |
259 | + in.value->day, |
260 | + in.value->hour, |
261 | + in.value->minute, |
262 | + in.value->second); |
263 | + g_time_zone_unref(gtz); |
264 | + return out; |
265 | + } |
266 | + |
267 | + static bool |
268 | + is_component_interesting(ECalComponent * component) |
269 | + { |
270 | + // we only want calendar events and vtodos |
271 | const auto vtype = e_cal_component_get_vtype(component); |
272 | - auto subtask = static_cast<AppointmentSubtask*>(gsubtask); |
273 | - |
274 | - if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO)) |
275 | - { |
276 | - const gchar* uid = nullptr; |
277 | - e_cal_component_get_uid(component, &uid); |
278 | - |
279 | - auto status = ICAL_STATUS_NONE; |
280 | - e_cal_component_get_status(component, &status); |
281 | - |
282 | - // get the timezone we want to use for generated Appointments/Alarms |
283 | - const char * location = icaltimezone_get_location(subtask->default_timezone); |
284 | - auto gtz = g_time_zone_new(location); |
285 | - g_debug("timezone abbreviation is %s", g_time_zone_get_abbreviation (gtz, 0)); |
286 | - |
287 | - const DateTime begin_dt { gtz, begin }; |
288 | - const DateTime end_dt { gtz, end }; |
289 | - g_debug ("got appointment from %s to %s, uid %s status %d", |
290 | - begin_dt.format("%F %T %z").c_str(), |
291 | - end_dt.format("%F %T %z").c_str(), |
292 | - uid, |
293 | - (int)status); |
294 | - |
295 | - // look for the in-house tags |
296 | - bool disabled = false; |
297 | - Appointment::Type type = Appointment::EVENT; |
298 | - GSList * categ_list = nullptr; |
299 | - e_cal_component_get_categories_list (component, &categ_list); |
300 | - for (GSList * l=categ_list; l!=nullptr; l=l->next) { |
301 | - auto tag = static_cast<const char*>(l->data); |
302 | - if (!g_strcmp0(tag, TAG_ALARM)) |
303 | - type = Appointment::UBUNTU_ALARM; |
304 | - if (!g_strcmp0(tag, TAG_DISABLED)) |
305 | - disabled = true; |
306 | - } |
307 | - e_cal_component_free_categories_list(categ_list); |
308 | - |
309 | - if ((uid != nullptr) && |
310 | - (!disabled) && |
311 | - (status != ICAL_STATUS_COMPLETED) && |
312 | - (status != ICAL_STATUS_CANCELLED)) |
313 | - { |
314 | - constexpr std::array<ECalComponentAlarmAction,1> omit = { (ECalComponentAlarmAction)-1 }; // list of action types to omit, terminated with -1 |
315 | - Appointment appointment; |
316 | - |
317 | - ECalComponentText text {}; |
318 | - e_cal_component_get_summary(component, &text); |
319 | - if (text.value) |
320 | - appointment.summary = text.value; |
321 | - |
322 | - auto icc = e_cal_component_get_icalcomponent(component); // component owns icc |
323 | - if (icc) |
324 | - { |
325 | - g_debug("%s", icalcomponent_as_ical_string(icc)); // libical owns this string; no leak |
326 | - |
327 | - auto icalprop = icalcomponent_get_first_property(icc, ICAL_X_PROPERTY); |
328 | - while (icalprop) |
329 | - { |
330 | - const char * x_name = icalproperty_get_x_name(icalprop); |
331 | - if ((x_name != nullptr) && !g_ascii_strcasecmp(x_name, X_PROP_ACTIVATION_URL)) |
332 | - { |
333 | - const char * url = icalproperty_get_value_as_string(icalprop); |
334 | - if ((url != nullptr) && appointment.activation_url.empty()) |
335 | - appointment.activation_url = url; |
336 | - } |
337 | - |
338 | - icalprop = icalcomponent_get_next_property(icc, ICAL_X_PROPERTY); |
339 | - } |
340 | - } |
341 | - |
342 | - appointment.begin = begin_dt; |
343 | - appointment.end = end_dt; |
344 | - appointment.color = subtask->color; |
345 | - appointment.uid = uid; |
346 | - appointment.type = type; |
347 | - |
348 | - auto e_alarms = e_cal_util_generate_alarms_for_comp(component, |
349 | - subtask->begin, |
350 | - subtask->end, |
351 | - const_cast<ECalComponentAlarmAction*>(omit.data()), |
352 | - e_cal_client_resolve_tzid_cb, |
353 | - subtask->client, |
354 | - nullptr); |
355 | - |
356 | - std::map<DateTime,Alarm> alarms; |
357 | - |
358 | - if (e_alarms != nullptr) |
359 | - { |
360 | - for (auto l=e_alarms->alarms; l!=nullptr; l=l->next) |
361 | - { |
362 | - auto ai = static_cast<ECalComponentAlarmInstance*>(l->data); |
363 | - auto a = e_cal_component_get_alarm(component, ai->auid); |
364 | - |
365 | - if (a != nullptr) |
366 | - { |
367 | - const DateTime alarm_begin{gtz, ai->trigger}; |
368 | - auto& alarm = alarms[alarm_begin]; |
369 | - |
370 | - if (alarm.text.empty()) |
371 | - alarm.text = get_alarm_text(a); |
372 | - if (alarm.audio_url.empty()) |
373 | - alarm.audio_url = get_alarm_sound_url(a); |
374 | - if (!alarm.time.is_set()) |
375 | - alarm.time = alarm_begin; |
376 | - |
377 | - e_cal_component_alarm_free(a); |
378 | - } |
379 | - } |
380 | - |
381 | - e_cal_component_alarms_free(e_alarms); |
382 | - } |
383 | - // Hm, no alarm triggers? |
384 | - // That's a bug in alarms created by some versions of ubuntu-ui-toolkit. |
385 | - // If that's what's happening here, let's handle those alarms anyway |
386 | - // by effectively injecting a TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
387 | - else if (appointment.is_ubuntu_alarm()) |
388 | - { |
389 | - Alarm tmp; |
390 | - tmp.time = appointment.begin; |
391 | - |
392 | - auto auids = e_cal_component_get_alarm_uids(component); |
393 | - for(auto l=auids; l!=nullptr; l=l->next) |
394 | - { |
395 | - const auto auid = static_cast<const char*>(l->data); |
396 | - auto a = e_cal_component_get_alarm(component, auid); |
397 | - if (a != nullptr) |
398 | - { |
399 | - if (tmp.text.empty()) |
400 | - tmp.text = get_alarm_text(a); |
401 | - if (tmp.audio_url.empty()) |
402 | - tmp.audio_url = get_alarm_sound_url(a); |
403 | - e_cal_component_alarm_free(a); |
404 | - } |
405 | - } |
406 | - cal_obj_uid_list_free(auids); |
407 | - |
408 | - alarms[tmp.time] = tmp; |
409 | - } |
410 | - |
411 | - appointment.alarms.reserve(alarms.size()); |
412 | - for (const auto& it : alarms) |
413 | - appointment.alarms.push_back(it.second); |
414 | - |
415 | - subtask->task->appointments.push_back(appointment); |
416 | - } |
417 | - |
418 | - g_time_zone_unref(gtz); |
419 | - } |
420 | - |
421 | - return G_SOURCE_CONTINUE; |
422 | + if ((vtype != E_CAL_COMPONENT_EVENT) && |
423 | + (vtype != E_CAL_COMPONENT_TODO)) |
424 | + return false; |
425 | + |
426 | + // we're not interested in completed or cancelled components |
427 | + auto status = ICAL_STATUS_NONE; |
428 | + e_cal_component_get_status(component, &status); |
429 | + if ((status == ICAL_STATUS_COMPLETED) || |
430 | + (status == ICAL_STATUS_CANCELLED)) |
431 | + return false; |
432 | + |
433 | + // we don't want disabled alarms |
434 | + bool disabled = false; |
435 | + GSList * categ_list = nullptr; |
436 | + e_cal_component_get_categories_list (component, &categ_list); |
437 | + for (GSList * l=categ_list; l!=nullptr; l=l->next) { |
438 | + auto tag = static_cast<const char*>(l->data); |
439 | + if (!g_strcmp0(tag, TAG_DISABLED)) |
440 | + disabled = true; |
441 | + } |
442 | + e_cal_component_free_categories_list(categ_list); |
443 | + if (disabled) |
444 | + return false; |
445 | + |
446 | + return true; |
447 | + } |
448 | + |
449 | + static Appointment |
450 | + get_appointment(ECalComponent * component, GTimeZone * gtz) |
451 | + { |
452 | + Appointment baseline; |
453 | + |
454 | + // get appointment.uid |
455 | + const gchar* uid = nullptr; |
456 | + e_cal_component_get_uid(component, &uid); |
457 | + if (uid != nullptr) |
458 | + baseline.uid = uid; |
459 | + |
460 | + // get appointment.summary |
461 | + ECalComponentText text {}; |
462 | + e_cal_component_get_summary(component, &text); |
463 | + if (text.value) |
464 | + baseline.summary = text.value; |
465 | + |
466 | + // get appointment.begin |
467 | + ECalComponentDateTime eccdt_tmp {}; |
468 | + e_cal_component_get_dtstart(component, &eccdt_tmp); |
469 | + baseline.begin = datetime_from_component_date_time(eccdt_tmp, gtz); |
470 | + e_cal_component_free_datetime(&eccdt_tmp); |
471 | + |
472 | + // get appointment.end |
473 | + e_cal_component_get_dtend(component, &eccdt_tmp); |
474 | + baseline.end = eccdt_tmp.value != nullptr |
475 | + ? datetime_from_component_date_time(eccdt_tmp, gtz) |
476 | + : baseline.begin; |
477 | + e_cal_component_free_datetime(&eccdt_tmp); |
478 | + |
479 | + // get appointment.activation_url from x-props |
480 | + auto icc = e_cal_component_get_icalcomponent(component); // icc owned by component |
481 | + auto icalprop = icalcomponent_get_first_property(icc, ICAL_X_PROPERTY); |
482 | + while (icalprop != nullptr) { |
483 | + const char * x_name = icalproperty_get_x_name(icalprop); |
484 | + if ((x_name != nullptr) && !g_ascii_strcasecmp(x_name, X_PROP_ACTIVATION_URL)) { |
485 | + const char * url = icalproperty_get_value_as_string(icalprop); |
486 | + if ((url != nullptr) && baseline.activation_url.empty()) |
487 | + baseline.activation_url = url; |
488 | + } |
489 | + icalprop = icalcomponent_get_next_property(icc, ICAL_X_PROPERTY); |
490 | + } |
491 | + |
492 | + // get appointment.type |
493 | + baseline.type = Appointment::EVENT; |
494 | + GSList * categ_list = nullptr; |
495 | + e_cal_component_get_categories_list (component, &categ_list); |
496 | + for (GSList * l=categ_list; l!=nullptr; l=l->next) { |
497 | + auto tag = static_cast<const char*>(l->data); |
498 | + if (!g_strcmp0(tag, TAG_ALARM)) |
499 | + baseline.type = Appointment::UBUNTU_ALARM; |
500 | + } |
501 | + e_cal_component_free_categories_list(categ_list); |
502 | + |
503 | + g_debug("%s got appointment from %s to %s: %s", G_STRLOC, |
504 | + baseline.begin.format("%F %T %z").c_str(), |
505 | + baseline.end.format("%F %T %z").c_str(), |
506 | + icalcomponent_as_ical_string(icc) /* string owned by ical */); |
507 | + |
508 | + return baseline; |
509 | + } |
510 | + |
511 | + static void |
512 | + add_event_to_subtask(ECalComponent * component, |
513 | + ClientSubtask * subtask, |
514 | + GTimeZone * gtz) |
515 | + { |
516 | + // events with alarms are covered by add_alarm_to_subtask(), |
517 | + // so skip them here |
518 | + auto auids = e_cal_component_get_alarm_uids(component); |
519 | + const bool has_alarms = auids != nullptr; |
520 | + cal_obj_uid_list_free(auids); |
521 | + if (has_alarms) |
522 | + return; |
523 | + |
524 | + // add it. simple, eh? |
525 | + if (is_component_interesting(component)) |
526 | + { |
527 | + Appointment appointment = get_appointment(component, gtz); |
528 | + appointment.color = subtask->color; |
529 | + subtask->task->appointments.push_back(appointment); |
530 | + } |
531 | + } |
532 | + |
533 | + static void |
534 | + add_alarms_to_subtask(ECalComponentAlarms * comp_alarms, |
535 | + ClientSubtask * subtask, |
536 | + GTimeZone * gtz) |
537 | + { |
538 | + auto& component = comp_alarms->comp; |
539 | + |
540 | + if (!is_component_interesting(component)) |
541 | + return; |
542 | + |
543 | + Appointment baseline = get_appointment(component, gtz); |
544 | + baseline.color = subtask->color; |
545 | + |
546 | + /** |
547 | + *** Now loop through comp_alarms to get information that we need |
548 | + *** to build the instance appointments and their alarms. |
549 | + *** |
550 | + *** Outer map key is the instance component's start + end time. |
551 | + *** We build Appointment.begin and .end from that. |
552 | + *** |
553 | + *** inner map key is the alarm trigger, we build Alarm.time from that. |
554 | + *** |
555 | + *** inner map value is the Alarm. |
556 | + *** |
557 | + *** We map the alarms based on their trigger time so that we |
558 | + *** can fold together multiple valarms that trigger for the |
559 | + *** same componeng at the same time. This is commonplace; |
560 | + *** e.g. one valarm will have a display action and another |
561 | + *** will specify a sound to be played. |
562 | + */ |
563 | + std::map<std::pair<DateTime,DateTime>,std::map<DateTime,Alarm>> alarms; |
564 | + for (auto l=comp_alarms->alarms; l!=nullptr; l=l->next) |
565 | + { |
566 | + auto ai = static_cast<ECalComponentAlarmInstance*>(l->data); |
567 | + auto a = e_cal_component_get_alarm(component, ai->auid); |
568 | + if (a == nullptr) |
569 | + continue; |
570 | + |
571 | + auto instance_time = std::make_pair(DateTime{gtz, ai->occur_start}, |
572 | + DateTime{gtz, ai->occur_end}); |
573 | + auto trigger_time = DateTime{gtz, ai->trigger}; |
574 | + |
575 | + auto& alarm = alarms[instance_time][trigger_time]; |
576 | + |
577 | + if (alarm.text.empty()) |
578 | + alarm.text = get_alarm_text(a); |
579 | + if (alarm.audio_url.empty()) |
580 | + alarm.audio_url = get_alarm_sound_url(a); |
581 | + if (!alarm.time.is_set()) |
582 | + alarm.time = trigger_time; |
583 | + |
584 | + e_cal_component_alarm_free(a); |
585 | + } |
586 | + |
587 | + for (auto& i : alarms) |
588 | + { |
589 | + Appointment appointment = baseline; |
590 | + appointment.begin = i.first.first; |
591 | + appointment.end = i.first.second; |
592 | + appointment.alarms.reserve(i.second.size()); |
593 | + for (auto& j : i.second) |
594 | + appointment.alarms.push_back(j.second); |
595 | + subtask->task->appointments.push_back(appointment); |
596 | + } |
597 | } |
598 | |
599 | /*** |
600 | |
601 | === modified file 'tests/CMakeLists.txt' |
602 | --- tests/CMakeLists.txt 2015-05-08 00:08:13 +0000 |
603 | +++ tests/CMakeLists.txt 2015-05-21 12:47:48 +0000 |
604 | @@ -78,25 +78,26 @@ |
605 | set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources3") |
606 | endif() |
607 | |
608 | -function(add_eds_test_by_name name) |
609 | +function(add_eds_ics_test_by_name name) |
610 | set (TEST_NAME ${name}) |
611 | add_executable(${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled) |
612 | target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) |
613 | add_test (${TEST_NAME} |
614 | - ${CMAKE_CURRENT_SOURCE_DIR}/run-eds-test.sh |
615 | - ${DBUS_RUNNER} # arg1: dbus-test-runner exec |
616 | - ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path |
617 | - ${TEST_NAME} # arg3: test name |
618 | - ${EVOLUTION_CALENDAR_FACTORY} # arg4: evolution-calendar-factory exec |
619 | - ${EVOLUTION_SOURCE_SERVICE_NAME} # arg5: dbus name for source registry |
620 | - ${EVOLUTION_SOURCE_REGISTRY} # arg6: evolution-source-registry exec |
621 | - ${GVFSD} # arg7: gvfsd exec |
622 | - ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}-config-files) # arg8: canned config files |
623 | + ${CMAKE_CURRENT_SOURCE_DIR}/run-eds-ics-test.sh |
624 | + ${DBUS_RUNNER} # arg1: dbus-test-runner exec |
625 | + ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path |
626 | + ${TEST_NAME} # arg3: test name |
627 | + ${EVOLUTION_CALENDAR_FACTORY} # arg4: evolution-calendar-factory exec |
628 | + ${EVOLUTION_SOURCE_SERVICE_NAME} # arg5: dbus name for source registry |
629 | + ${EVOLUTION_SOURCE_REGISTRY} # arg6: evolution-source-registry exec |
630 | + ${GVFSD} # arg7: gvfsd exec |
631 | + ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg8: base directory for config file template |
632 | + ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.ics) # arg9: the ical file for this test |
633 | endfunction() |
634 | -add_eds_test_by_name(test-eds-tasks) |
635 | -add_eds_test_by_name(test-eds-valarms) |
636 | - |
637 | - |
638 | +add_eds_ics_test_by_name(test-eds-ics-all-day-events) |
639 | +add_eds_ics_test_by_name(test-eds-ics-repeating-events) |
640 | +add_eds_ics_test_by_name(test-eds-ics-nonrepeating-events) |
641 | +add_eds_ics_test_by_name(test-eds-ics-repeating-valarms) |
642 | |
643 | |
644 | # disabling the timezone unit tests because they require |
645 | |
646 | === modified file 'tests/print-to.h' |
647 | --- tests/print-to.h 2015-04-06 15:20:49 +0000 |
648 | +++ tests/print-to.h 2015-05-21 12:47:48 +0000 |
649 | @@ -33,9 +33,18 @@ |
650 | ***/ |
651 | |
652 | void |
653 | +PrintTo(const DateTime& datetime, std::ostream* os) |
654 | +{ |
655 | + *os << "{time:'" << datetime.format("%F %T %z") << '}'; |
656 | +} |
657 | + |
658 | +void |
659 | PrintTo(const Alarm& alarm, std::ostream* os) |
660 | { |
661 | - *os << "{text:'" << alarm.text << "', audio_url:'" << alarm.audio_url << "', time:'"<<alarm.time.format("%F %T")<<"'}"; |
662 | + *os << '{'; |
663 | + *os << "{text:" << alarm.text << '}'; |
664 | + PrintTo(alarm.time, os); |
665 | + *os << '}'; |
666 | } |
667 | |
668 | } // namespace datetime |
669 | |
670 | === renamed file 'tests/run-eds-test.sh' => 'tests/run-eds-ics-test.sh' |
671 | --- tests/run-eds-test.sh 2015-04-06 20:09:16 +0000 |
672 | +++ tests/run-eds-ics-test.sh 2015-05-21 12:47:48 +0000 |
673 | @@ -9,6 +9,7 @@ |
674 | echo ARG6=$6 # full exectuable path of evolution-source-registry |
675 | echo ARG7=$7 # full executable path of gvfs |
676 | echo ARG8=$8 # config files |
677 | +echo ARG8=$9 # ics file |
678 | |
679 | # set up the tmpdir and tell the shell to purge it when we exit |
680 | export TEST_TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d $3-XXXXXXXXXX) || exit 1 |
681 | @@ -32,6 +33,9 @@ |
682 | export QORGANIZER_EDS_DEBUG=On |
683 | export GIO_USE_VFS=local # needed to ensure GVFS shuts down cleanly after the test is over |
684 | |
685 | +export G_MESSAGES_DEBUG=all |
686 | +export G_DBUS_DEBUG=messages |
687 | + |
688 | echo HOMEDIR=${HOME} |
689 | rm -rf ${XDG_DATA_HOME} |
690 | |
691 | @@ -41,6 +45,12 @@ |
692 | cp --verbose --archive $8/. $HOME |
693 | fi |
694 | |
695 | +# if there's a specific ics file to test, copy it on top of the canned confilg files |
696 | +if [ -e $9 ]; then |
697 | + echo "copying $9 into $HOME" |
698 | + cp --verbose --archive $9 ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics |
699 | +fi |
700 | + |
701 | # run dbus-test-runner |
702 | $1 --keep-env --max-wait=90 \ |
703 | --task $2 --task-name $3 --wait-until-complete --wait-for=org.gnome.evolution.dataserver.Calendar4 \ |
704 | |
705 | === added file 'tests/test-eds-ics-all-day-events.cpp' |
706 | --- tests/test-eds-ics-all-day-events.cpp 1970-01-01 00:00:00 +0000 |
707 | +++ tests/test-eds-ics-all-day-events.cpp 2015-05-21 12:47:48 +0000 |
708 | @@ -0,0 +1,91 @@ |
709 | +/* |
710 | + * Copyright 2015 Canonical Ltd. |
711 | + * |
712 | + * This program is free software: you can redistribute it and/or modify it |
713 | + * under the terms of the GNU General Public License version 3, as published |
714 | + * by the Free Software Foundation. |
715 | + * |
716 | + * This program is distributed in the hope that it will be useful, but |
717 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
718 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
719 | + * PURPOSE. See the GNU General Public License for more details. |
720 | + * |
721 | + * You should have received a copy of the GNU General Public License along |
722 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
723 | + * |
724 | + * Authors: |
725 | + * Charles Kerr <charles.kerr@canonical.com> |
726 | + */ |
727 | + |
728 | +#include <algorithm> |
729 | + |
730 | +#include <datetime/alarm-queue-simple.h> |
731 | +#include <datetime/clock-mock.h> |
732 | +#include <datetime/engine-eds.h> |
733 | +#include <datetime/planner-range.h> |
734 | + |
735 | +#include <gtest/gtest.h> |
736 | + |
737 | +#include "glib-fixture.h" |
738 | +#include "print-to.h" |
739 | +#include "timezone-mock.h" |
740 | +#include "wakeup-timer-mock.h" |
741 | + |
742 | +using namespace unity::indicator::datetime; |
743 | +using VAlarmFixture = GlibFixture; |
744 | + |
745 | +/*** |
746 | +**** |
747 | +***/ |
748 | + |
749 | +TEST_F(VAlarmFixture, MultipleAppointments) |
750 | +{ |
751 | + // start the EDS engine |
752 | + auto engine = std::make_shared<EdsEngine>(); |
753 | + |
754 | + // we need a consistent timezone for the planner and our local DateTimes |
755 | + constexpr char const * zone_str {"America/Chicago"}; |
756 | + auto tz = std::make_shared<MockTimezone>(zone_str); |
757 | + auto gtz = g_time_zone_new(zone_str); |
758 | + |
759 | + // make a planner that looks at the first half of 2015 in EDS |
760 | + auto planner = std::make_shared<SimpleRangePlanner>(engine, tz); |
761 | + const DateTime range_begin {gtz, 2015,1, 1, 0, 0, 0.0}; |
762 | + const DateTime range_end {gtz, 2015,6,31,23,59,59.5}; |
763 | + planner->range().set(std::make_pair(range_begin, range_end)); |
764 | + |
765 | + // give EDS a moment to load |
766 | + if (planner->appointments().get().empty()) { |
767 | + g_message("waiting a moment for EDS to load..."); |
768 | + auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){ |
769 | + g_message("ah, they loaded"); |
770 | + if (!appointments.empty()) |
771 | + g_main_loop_quit(loop); |
772 | + }; |
773 | + core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed)); |
774 | + constexpr int max_wait_sec = 10; |
775 | + wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND); |
776 | + } |
777 | + |
778 | + // what we expect to get... |
779 | + Appointment expected_appt; |
780 | + expected_appt.uid = "20150521T111538Z-7449-1000-3572-0@ghidorah"; |
781 | + expected_appt.color = "#becedd"; |
782 | + expected_appt.summary = "Memorial Day"; |
783 | + expected_appt.begin = DateTime{gtz,2015,5,25,0,0,0}; |
784 | + expected_appt.end = DateTime{gtz,2015,5,26,0,0,0}; |
785 | + |
786 | + // compare it to what we actually loaded... |
787 | + const auto appts = planner->appointments().get(); |
788 | + ASSERT_EQ(1, appts.size()); |
789 | + const auto& appt = appts[0]; |
790 | + EXPECT_EQ(expected_appt.begin, appt.begin); |
791 | + EXPECT_EQ(expected_appt.end, appt.end); |
792 | + EXPECT_EQ(expected_appt.uid, appt.uid); |
793 | + EXPECT_EQ(expected_appt.color, appt.color); |
794 | + EXPECT_EQ(expected_appt.summary, appt.summary); |
795 | + EXPECT_EQ(0, appt.alarms.size()); |
796 | + |
797 | + // cleanup |
798 | + g_time_zone_unref(gtz); |
799 | +} |
800 | |
801 | === added file 'tests/test-eds-ics-all-day-events.ics' |
802 | --- tests/test-eds-ics-all-day-events.ics 1970-01-01 00:00:00 +0000 |
803 | +++ tests/test-eds-ics-all-day-events.ics 2015-05-21 12:47:48 +0000 |
804 | @@ -0,0 +1,19 @@ |
805 | +BEGIN:VCALENDAR |
806 | +CALSCALE:GREGORIAN |
807 | +PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
808 | +VERSION:2.0 |
809 | +X-EVOLUTION-DATA-REVISION:2015-05-07T21:14:49.315443Z(0) |
810 | +BEGIN:VEVENT |
811 | +UID:20150521T111538Z-7449-1000-3572-0@ghidorah |
812 | +DTSTAMP:20150521T001128Z |
813 | +DTSTART;VALUE=DATE:20150525 |
814 | +DTEND;VALUE=DATE:20150526 |
815 | +TRANSP:TRANSPARENT |
816 | +SEQUENCE:2 |
817 | +SUMMARY:Memorial Day |
818 | +DESCRIPTION:Today is Memorial Day |
819 | +CLASS:PUBLIC |
820 | +CREATED:20150521T111638Z |
821 | +LAST-MODIFIED:20150521T111638Z |
822 | +END:VEVENT |
823 | +END:VCALENDAR |
824 | |
825 | === added directory 'tests/test-eds-ics-config-files' |
826 | === added directory 'tests/test-eds-ics-config-files/.config' |
827 | === added directory 'tests/test-eds-ics-config-files/.config/evolution' |
828 | === added directory 'tests/test-eds-ics-config-files/.config/evolution/sources' |
829 | === added file 'tests/test-eds-ics-config-files/.config/evolution/sources/system-proxy.source' |
830 | --- tests/test-eds-ics-config-files/.config/evolution/sources/system-proxy.source 1970-01-01 00:00:00 +0000 |
831 | +++ tests/test-eds-ics-config-files/.config/evolution/sources/system-proxy.source 2015-05-21 12:47:48 +0000 |
832 | @@ -0,0 +1,21 @@ |
833 | + |
834 | +[Data Source] |
835 | +DisplayName=Default Proxy Settings |
836 | +Enabled=true |
837 | +Parent= |
838 | + |
839 | +[Proxy] |
840 | +Method=default |
841 | +IgnoreHosts=localhost;127.0.0.0/8;::1; |
842 | +AutoconfigUrl= |
843 | +FtpHost= |
844 | +FtpPort=0 |
845 | +HttpAuthPassword= |
846 | +HttpAuthUser= |
847 | +HttpHost= |
848 | +HttpPort=8080 |
849 | +HttpUseAuth=false |
850 | +HttpsHost= |
851 | +HttpsPort=0 |
852 | +SocksHost= |
853 | +SocksPort=0 |
854 | |
855 | === added directory 'tests/test-eds-ics-config-files/.local' |
856 | === added directory 'tests/test-eds-ics-config-files/.local/share' |
857 | === added directory 'tests/test-eds-ics-config-files/.local/share/evolution' |
858 | === added directory 'tests/test-eds-ics-config-files/.local/share/evolution/calendar' |
859 | === added directory 'tests/test-eds-ics-config-files/.local/share/evolution/calendar/system' |
860 | === added directory 'tests/test-eds-ics-config-files/.local/share/evolution/tasks' |
861 | === added directory 'tests/test-eds-ics-config-files/.local/share/evolution/tasks/system' |
862 | === added file 'tests/test-eds-ics-nonrepeating-events.cpp' |
863 | --- tests/test-eds-ics-nonrepeating-events.cpp 1970-01-01 00:00:00 +0000 |
864 | +++ tests/test-eds-ics-nonrepeating-events.cpp 2015-05-21 12:47:48 +0000 |
865 | @@ -0,0 +1,93 @@ |
866 | +/* |
867 | + * Copyright 2015 Canonical Ltd. |
868 | + * |
869 | + * This program is free software: you can redistribute it and/or modify it |
870 | + * under the terms of the GNU General Public License version 3, as published |
871 | + * by the Free Software Foundation. |
872 | + * |
873 | + * This program is distributed in the hope that it will be useful, but |
874 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
875 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
876 | + * PURPOSE. See the GNU General Public License for more details. |
877 | + * |
878 | + * You should have received a copy of the GNU General Public License along |
879 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
880 | + * |
881 | + * Authors: |
882 | + * Charles Kerr <charles.kerr@canonical.com> |
883 | + */ |
884 | + |
885 | +#include <algorithm> |
886 | + |
887 | +#include <datetime/alarm-queue-simple.h> |
888 | +#include <datetime/clock-mock.h> |
889 | +#include <datetime/engine-eds.h> |
890 | +#include <datetime/planner-range.h> |
891 | + |
892 | +#include <gtest/gtest.h> |
893 | + |
894 | +#include "glib-fixture.h" |
895 | +#include "print-to.h" |
896 | +#include "timezone-mock.h" |
897 | +#include "wakeup-timer-mock.h" |
898 | + |
899 | +using namespace unity::indicator::datetime; |
900 | +using VAlarmFixture = GlibFixture; |
901 | + |
902 | +/*** |
903 | +**** |
904 | +***/ |
905 | + |
906 | +TEST_F(VAlarmFixture, MultipleAppointments) |
907 | +{ |
908 | + // start the EDS engine |
909 | + auto engine = std::make_shared<EdsEngine>(); |
910 | + |
911 | + // we need a consistent timezone for the planner and our local DateTimes |
912 | + constexpr char const * zone_str {"America/Chicago"}; |
913 | + auto tz = std::make_shared<MockTimezone>(zone_str); |
914 | + auto gtz = g_time_zone_new(zone_str); |
915 | + |
916 | + // make a planner that looks at the first half of 2015 in EDS |
917 | + auto planner = std::make_shared<SimpleRangePlanner>(engine, tz); |
918 | + const DateTime range_begin {gtz, 2015,1, 1, 0, 0, 0.0}; |
919 | + const DateTime range_end {gtz, 2015,6,31,23,59,59.5}; |
920 | + planner->range().set(std::make_pair(range_begin, range_end)); |
921 | + |
922 | + // give EDS a moment to load |
923 | + if (planner->appointments().get().empty()) { |
924 | + g_message("waiting a moment for EDS to load..."); |
925 | + auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){ |
926 | + g_message("ah, they loaded"); |
927 | + if (!appointments.empty()) |
928 | + g_main_loop_quit(loop); |
929 | + }; |
930 | + core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed)); |
931 | + constexpr int max_wait_sec = 10; |
932 | + wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND); |
933 | + } |
934 | + |
935 | + // what we expect to get... |
936 | + Appointment expected_appt; |
937 | + expected_appt.uid = "20150520T000726Z-3878-32011-1770-81@ubuntu-phablet"; |
938 | + expected_appt.color = "#becedd"; |
939 | + expected_appt.summary = "Alarm"; |
940 | + std::array<Alarm,1> expected_alarms = { |
941 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,20,20,00,0)}) |
942 | + }; |
943 | + |
944 | + // compare it to what we actually loaded... |
945 | + const auto appts = planner->appointments().get(); |
946 | + EXPECT_EQ(expected_alarms.size(), appts.size()); |
947 | + for (size_t i=0, n=expected_alarms.size(); i<n; i++) { |
948 | + const auto& appt = appts[i]; |
949 | + EXPECT_EQ(expected_appt.uid, appt.uid); |
950 | + EXPECT_EQ(expected_appt.color, appt.color); |
951 | + EXPECT_EQ(expected_appt.summary, appt.summary); |
952 | + EXPECT_EQ(1, appt.alarms.size()); |
953 | + EXPECT_EQ(expected_alarms[i], appt.alarms[0]); |
954 | + } |
955 | + |
956 | + // cleanup |
957 | + g_time_zone_unref(gtz); |
958 | +} |
959 | |
960 | === added file 'tests/test-eds-ics-nonrepeating-events.ics' |
961 | --- tests/test-eds-ics-nonrepeating-events.ics 1970-01-01 00:00:00 +0000 |
962 | +++ tests/test-eds-ics-nonrepeating-events.ics 2015-05-21 12:47:48 +0000 |
963 | @@ -0,0 +1,27 @@ |
964 | +BEGIN:VCALENDAR |
965 | +CALSCALE:GREGORIAN |
966 | +PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
967 | +VERSION:2.0 |
968 | +X-EVOLUTION-DATA-REVISION:2015-05-20T22:39:32.685099Z(1) |
969 | +BEGIN:VTODO |
970 | +UID:20150520T000726Z-3878-32011-1770-81@ubuntu-phablet |
971 | +DTSTAMP:20150520T223932Z |
972 | +DTSTART:20150520T200000 |
973 | +SUMMARY:Alarm |
974 | +CATEGORIES:x-canonical-alarm |
975 | +SEQUENCE:1 |
976 | +LAST-MODIFIED:20150520T223932Z |
977 | +BEGIN:VALARM |
978 | +X-EVOLUTION-ALARM-UID:20150520T223932Z-22506-32011-1771-2@ubuntu-phablet |
979 | +ACTION:AUDIO |
980 | +ATTACH:file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg |
981 | +TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
982 | +END:VALARM |
983 | +BEGIN:VALARM |
984 | +X-EVOLUTION-ALARM-UID:20150520T223932Z-22506-32011-1771-3@ubuntu-phablet |
985 | +ACTION:DISPLAY |
986 | +DESCRIPTION:Alarm |
987 | +TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
988 | +END:VALARM |
989 | +END:VTODO |
990 | +END:VCALENDAR |
991 | |
992 | === added file 'tests/test-eds-ics-repeating-events.cpp' |
993 | --- tests/test-eds-ics-repeating-events.cpp 1970-01-01 00:00:00 +0000 |
994 | +++ tests/test-eds-ics-repeating-events.cpp 2015-05-21 12:47:48 +0000 |
995 | @@ -0,0 +1,100 @@ |
996 | +/* |
997 | + * Copyright 2015 Canonical Ltd. |
998 | + * |
999 | + * This program is free software: you can redistribute it and/or modify it |
1000 | + * under the terms of the GNU General Public License version 3, as published |
1001 | + * by the Free Software Foundation. |
1002 | + * |
1003 | + * This program is distributed in the hope that it will be useful, but |
1004 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1005 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1006 | + * PURPOSE. See the GNU General Public License for more details. |
1007 | + * |
1008 | + * You should have received a copy of the GNU General Public License along |
1009 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1010 | + * |
1011 | + * Authors: |
1012 | + * Charles Kerr <charles.kerr@canonical.com> |
1013 | + */ |
1014 | + |
1015 | +#include <algorithm> |
1016 | + |
1017 | +#include <datetime/alarm-queue-simple.h> |
1018 | +#include <datetime/clock-mock.h> |
1019 | +#include <datetime/engine-eds.h> |
1020 | +#include <datetime/planner-range.h> |
1021 | + |
1022 | +#include <gtest/gtest.h> |
1023 | + |
1024 | +#include "glib-fixture.h" |
1025 | +#include "print-to.h" |
1026 | +#include "timezone-mock.h" |
1027 | +#include "wakeup-timer-mock.h" |
1028 | + |
1029 | +using namespace unity::indicator::datetime; |
1030 | +using VAlarmFixture = GlibFixture; |
1031 | + |
1032 | +/*** |
1033 | +**** |
1034 | +***/ |
1035 | + |
1036 | +TEST_F(VAlarmFixture, MultipleAppointments) |
1037 | +{ |
1038 | + // start the EDS engine |
1039 | + auto engine = std::make_shared<EdsEngine>(); |
1040 | + |
1041 | + // we need a consistent timezone for the planner and our local DateTimes |
1042 | + constexpr char const * zone_str {"America/Chicago"}; |
1043 | + auto tz = std::make_shared<MockTimezone>(zone_str); |
1044 | + auto gtz = g_time_zone_new(zone_str); |
1045 | + |
1046 | + // make a planner that looks at the first half of 2015 in EDS |
1047 | + auto planner = std::make_shared<SimpleRangePlanner>(engine, tz); |
1048 | + const DateTime range_begin {gtz, 2015,1, 1, 0, 0, 0.0}; |
1049 | + const DateTime range_end {gtz, 2015,6,31,23,59,59.5}; |
1050 | + planner->range().set(std::make_pair(range_begin, range_end)); |
1051 | + |
1052 | + // give EDS a moment to load |
1053 | + if (planner->appointments().get().empty()) { |
1054 | + g_message("waiting a moment for EDS to load..."); |
1055 | + auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){ |
1056 | + g_message("ah, they loaded"); |
1057 | + if (!appointments.empty()) |
1058 | + g_main_loop_quit(loop); |
1059 | + }; |
1060 | + core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed)); |
1061 | + constexpr int max_wait_sec = 10; |
1062 | + wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND); |
1063 | + } |
1064 | + |
1065 | + // what we expect to get... |
1066 | + Appointment expected_appt; |
1067 | + expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@ubuntu-phablet"; |
1068 | + expected_appt.color = "#becedd"; |
1069 | + expected_appt.summary = "Alarm"; |
1070 | + std::array<Alarm,8> expected_alarms = { |
1071 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5, 8,16,40,0)}), |
1072 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,15,16,40,0)}), |
1073 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,22,16,40,0)}), |
1074 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,29,16,40,0)}), |
1075 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6, 5,16,40,0)}), |
1076 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,12,16,40,0)}), |
1077 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,19,16,40,0)}), |
1078 | + Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,26,16,40,0)}) |
1079 | + }; |
1080 | + |
1081 | + // compare it to what we actually loaded... |
1082 | + const auto appts = planner->appointments().get(); |
1083 | + EXPECT_EQ(expected_alarms.size(), appts.size()); |
1084 | + for (size_t i=0, n=expected_alarms.size(); i<n; i++) { |
1085 | + const auto& appt = appts[i]; |
1086 | + EXPECT_EQ(expected_appt.uid, appt.uid); |
1087 | + EXPECT_EQ(expected_appt.color, appt.color); |
1088 | + EXPECT_EQ(expected_appt.summary, appt.summary); |
1089 | + EXPECT_EQ(1, appt.alarms.size()); |
1090 | + EXPECT_EQ(expected_alarms[i], appt.alarms[0]); |
1091 | + } |
1092 | + |
1093 | + // cleanup |
1094 | + g_time_zone_unref(gtz); |
1095 | +} |
1096 | |
1097 | === added file 'tests/test-eds-ics-repeating-events.ics' |
1098 | --- tests/test-eds-ics-repeating-events.ics 1970-01-01 00:00:00 +0000 |
1099 | +++ tests/test-eds-ics-repeating-events.ics 2015-05-21 12:47:48 +0000 |
1100 | @@ -0,0 +1,28 @@ |
1101 | +BEGIN:VCALENDAR |
1102 | +CALSCALE:GREGORIAN |
1103 | +PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
1104 | +VERSION:2.0 |
1105 | +X-EVOLUTION-DATA-REVISION:2015-05-07T21:14:49.315443Z(0) |
1106 | +BEGIN:VTODO |
1107 | +UID:20150507T211449Z-4262-32011-1418-1@ubuntu-phablet |
1108 | +DTSTAMP:20150508T211449Z |
1109 | +DTSTART:20150508T164000 |
1110 | +RRULE:FREQ=WEEKLY;BYDAY=FR |
1111 | +SUMMARY:Alarm |
1112 | +CATEGORIES:x-canonical-alarm |
1113 | +CREATED:20150507T211449Z |
1114 | +LAST-MODIFIED:20150507T211449Z |
1115 | +BEGIN:VALARM |
1116 | +X-EVOLUTION-ALARM-UID:20150507T211449Z-4262-32011-1418-2@ubuntu-phablet |
1117 | +ACTION:AUDIO |
1118 | +ATTACH:file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg |
1119 | +TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
1120 | +END:VALARM |
1121 | +BEGIN:VALARM |
1122 | +X-EVOLUTION-ALARM-UID:20150507T211449Z-4262-32011-1418-3@ubuntu-phablet |
1123 | +ACTION:DISPLAY |
1124 | +DESCRIPTION:Alarm |
1125 | +TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
1126 | +END:VALARM |
1127 | +END:VTODO |
1128 | +END:VCALENDAR |
1129 | |
1130 | === renamed file 'tests/test-eds-valarms.cpp' => 'tests/test-eds-ics-repeating-valarms.cpp' |
1131 | === added file 'tests/test-eds-ics-repeating-valarms.ics' |
1132 | --- tests/test-eds-ics-repeating-valarms.ics 1970-01-01 00:00:00 +0000 |
1133 | +++ tests/test-eds-ics-repeating-valarms.ics 2015-05-21 12:47:48 +0000 |
1134 | @@ -0,0 +1,47 @@ |
1135 | +BEGIN:VCALENDAR |
1136 | +CALSCALE:GREGORIAN |
1137 | +PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
1138 | +VERSION:2.0 |
1139 | +X-EVOLUTION-DATA-REVISION:2015-04-05T21:32:47.354433Z(2) |
1140 | +BEGIN:VEVENT |
1141 | +UID:20150405T213247Z-4371-32011-1698-1@ubuntu-phablet |
1142 | +DTSTAMP:20150405T213247Z |
1143 | +DTSTART:20150424T183500Z |
1144 | +DTEND:20150424T193554Z |
1145 | +X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:Can't parse as RECUR value |
1146 | + in RRULE property. Removing entire property: ERROR: No Value |
1147 | +SUMMARY:London Sprint Flight |
1148 | +CREATED:20150405T213247Z |
1149 | +LAST-MODIFIED:20150405T213247Z |
1150 | +BEGIN:VALARM |
1151 | +X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-2@ubuntu-phablet |
1152 | +ACTION:AUDIO |
1153 | +TRIGGER;VALUE=DURATION;RELATED=START:-P1D |
1154 | +REPEAT:3 |
1155 | +DURATION:PT2M |
1156 | +END:VALARM |
1157 | +BEGIN:VALARM |
1158 | +X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-3@ubuntu-phablet |
1159 | +ACTION:DISPLAY |
1160 | +DESCRIPTION:Time to pack! |
1161 | +TRIGGER;VALUE=DURATION;RELATED=START:-P1D |
1162 | +REPEAT:3 |
1163 | +DURATION:PT2M |
1164 | +END:VALARM |
1165 | +BEGIN:VALARM |
1166 | +X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-5@ubuntu-phablet |
1167 | +ACTION:AUDIO |
1168 | +TRIGGER;VALUE=DURATION;RELATED=START:-PT3H |
1169 | +REPEAT:3 |
1170 | +DURATION:PT2M |
1171 | +END:VALARM |
1172 | +BEGIN:VALARM |
1173 | +X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-6@ubuntu-phablet |
1174 | +ACTION:DISPLAY |
1175 | +DESCRIPTION:Go to the airport! |
1176 | +TRIGGER;VALUE=DURATION;RELATED=START:-PT3H |
1177 | +REPEAT:3 |
1178 | +DURATION:PT2M |
1179 | +END:VALARM |
1180 | +END:VEVENT |
1181 | +END:VCALENDAR |
1182 | |
1183 | === removed directory 'tests/test-eds-tasks-config-files' |
1184 | === removed directory 'tests/test-eds-tasks-config-files/.config' |
1185 | === removed directory 'tests/test-eds-tasks-config-files/.config/evolution' |
1186 | === removed directory 'tests/test-eds-tasks-config-files/.config/evolution/sources' |
1187 | === removed file 'tests/test-eds-tasks-config-files/.config/evolution/sources/system-proxy.source' |
1188 | --- tests/test-eds-tasks-config-files/.config/evolution/sources/system-proxy.source 2015-05-08 00:08:13 +0000 |
1189 | +++ tests/test-eds-tasks-config-files/.config/evolution/sources/system-proxy.source 1970-01-01 00:00:00 +0000 |
1190 | @@ -1,21 +0,0 @@ |
1191 | - |
1192 | -[Data Source] |
1193 | -DisplayName=Default Proxy Settings |
1194 | -Enabled=true |
1195 | -Parent= |
1196 | - |
1197 | -[Proxy] |
1198 | -Method=default |
1199 | -IgnoreHosts=localhost;127.0.0.0/8;::1; |
1200 | -AutoconfigUrl= |
1201 | -FtpHost= |
1202 | -FtpPort=0 |
1203 | -HttpAuthPassword= |
1204 | -HttpAuthUser= |
1205 | -HttpHost= |
1206 | -HttpPort=8080 |
1207 | -HttpUseAuth=false |
1208 | -HttpsHost= |
1209 | -HttpsPort=0 |
1210 | -SocksHost= |
1211 | -SocksPort=0 |
1212 | |
1213 | === removed directory 'tests/test-eds-tasks-config-files/.local' |
1214 | === removed directory 'tests/test-eds-tasks-config-files/.local/share' |
1215 | === removed directory 'tests/test-eds-tasks-config-files/.local/share/evolution' |
1216 | === removed directory 'tests/test-eds-tasks-config-files/.local/share/evolution/tasks' |
1217 | === removed directory 'tests/test-eds-tasks-config-files/.local/share/evolution/tasks/system' |
1218 | === removed file 'tests/test-eds-tasks-config-files/.local/share/evolution/tasks/system/tasks.ics' |
1219 | --- tests/test-eds-tasks-config-files/.local/share/evolution/tasks/system/tasks.ics 2015-05-08 00:08:13 +0000 |
1220 | +++ tests/test-eds-tasks-config-files/.local/share/evolution/tasks/system/tasks.ics 1970-01-01 00:00:00 +0000 |
1221 | @@ -1,28 +0,0 @@ |
1222 | -BEGIN:VCALENDAR |
1223 | -CALSCALE:GREGORIAN |
1224 | -PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
1225 | -VERSION:2.0 |
1226 | -X-EVOLUTION-DATA-REVISION:2015-05-07T21:14:49.315443Z(0) |
1227 | -BEGIN:VTODO |
1228 | -UID:20150507T211449Z-4262-32011-1418-1@ubuntu-phablet |
1229 | -DTSTAMP:20150508T211449Z |
1230 | -DTSTART:20150508T164000 |
1231 | -RRULE:FREQ=WEEKLY;BYDAY=FR |
1232 | -SUMMARY:Alarm |
1233 | -CATEGORIES:x-canonical-alarm |
1234 | -CREATED:20150507T211449Z |
1235 | -LAST-MODIFIED:20150507T211449Z |
1236 | -BEGIN:VALARM |
1237 | -X-EVOLUTION-ALARM-UID:20150507T211449Z-4262-32011-1418-2@ubuntu-phablet |
1238 | -ACTION:AUDIO |
1239 | -ATTACH:file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg |
1240 | -TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
1241 | -END:VALARM |
1242 | -BEGIN:VALARM |
1243 | -X-EVOLUTION-ALARM-UID:20150507T211449Z-4262-32011-1418-3@ubuntu-phablet |
1244 | -ACTION:DISPLAY |
1245 | -DESCRIPTION:Alarm |
1246 | -TRIGGER;VALUE=DURATION;RELATED=START:PT0S |
1247 | -END:VALARM |
1248 | -END:VTODO |
1249 | -END:VCALENDAR |
1250 | |
1251 | === removed file 'tests/test-eds-tasks.cpp' |
1252 | --- tests/test-eds-tasks.cpp 2015-05-08 00:08:13 +0000 |
1253 | +++ tests/test-eds-tasks.cpp 1970-01-01 00:00:00 +0000 |
1254 | @@ -1,101 +0,0 @@ |
1255 | -/* |
1256 | - * Copyright 2015 Canonical Ltd. |
1257 | - * |
1258 | - * This program is free software: you can redistribute it and/or modify it |
1259 | - * under the terms of the GNU General Public License version 3, as published |
1260 | - * by the Free Software Foundation. |
1261 | - * |
1262 | - * This program is distributed in the hope that it will be useful, but |
1263 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
1264 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1265 | - * PURPOSE. See the GNU General Public License for more details. |
1266 | - * |
1267 | - * You should have received a copy of the GNU General Public License along |
1268 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
1269 | - * |
1270 | - * Authors: |
1271 | - * Charles Kerr <charles.kerr@canonical.com> |
1272 | - */ |
1273 | - |
1274 | -#include <algorithm> |
1275 | - |
1276 | -#include <datetime/alarm-queue-simple.h> |
1277 | -#include <datetime/clock-mock.h> |
1278 | -#include <datetime/engine-eds.h> |
1279 | -#include <datetime/planner-range.h> |
1280 | - |
1281 | -#include <gtest/gtest.h> |
1282 | - |
1283 | -#include "glib-fixture.h" |
1284 | -#include "print-to.h" |
1285 | -#include "timezone-mock.h" |
1286 | -#include "wakeup-timer-mock.h" |
1287 | - |
1288 | -using namespace unity::indicator::datetime; |
1289 | -using VAlarmFixture = GlibFixture; |
1290 | - |
1291 | -/*** |
1292 | -**** |
1293 | -***/ |
1294 | - |
1295 | -TEST_F(VAlarmFixture, MultipleAppointments) |
1296 | -{ |
1297 | - // start the EDS engine |
1298 | - auto engine = std::make_shared<EdsEngine>(); |
1299 | - |
1300 | - // we need a consistent timezone for the planner and our local DateTimes |
1301 | - constexpr char const * zone_str {"America/Chicago"}; |
1302 | - auto tz = std::make_shared<MockTimezone>(zone_str); |
1303 | - auto gtz = g_time_zone_new(zone_str); |
1304 | - |
1305 | - // make a planner that looks at the first half of 2015 in EDS |
1306 | - auto planner = std::make_shared<SimpleRangePlanner>(engine, tz); |
1307 | - const DateTime range_begin {gtz, 2015,1, 1, 0, 0, 0.0}; |
1308 | - const DateTime range_end {gtz, 2015,6,31,23,59,59.5}; |
1309 | - planner->range().set(std::make_pair(range_begin, range_end)); |
1310 | - |
1311 | - // give EDS a moment to load |
1312 | - if (planner->appointments().get().empty()) { |
1313 | - g_message("waiting a moment for EDS to load..."); |
1314 | - auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){ |
1315 | - g_message("ah, they loaded"); |
1316 | - if (!appointments.empty()) |
1317 | - g_main_loop_quit(loop); |
1318 | - }; |
1319 | - core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed)); |
1320 | - constexpr int max_wait_sec = 10; |
1321 | - wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND); |
1322 | - } |
1323 | - |
1324 | - // what we expect to get... |
1325 | - Appointment expected_appt; |
1326 | - expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@ubuntu-phablet"; |
1327 | - expected_appt.color = "#becedd"; |
1328 | - expected_appt.summary = "Alarm"; |
1329 | - std::array<Alarm,8> expected_alarms = { |
1330 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5, 8,16,40,0)}), |
1331 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,15,16,40,0)}), |
1332 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,22,16,40,0)}), |
1333 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,5,29,16,40,0)}), |
1334 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6, 5,16,40,0)}), |
1335 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,12,16,40,0)}), |
1336 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,19,16,40,0)}), |
1337 | - Alarm({"Alarm", "file:///usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg", DateTime(gtz,2015,6,26,16,40,0)}) |
1338 | - }; |
1339 | - |
1340 | - // compare it to what we actually loaded... |
1341 | - const auto appts = planner->appointments().get(); |
1342 | - EXPECT_EQ(expected_alarms.size(), appts.size()); |
1343 | - for (size_t i=0, n=expected_alarms.size(); i<n; i++) { |
1344 | - const auto& appt = appts[i]; |
1345 | - EXPECT_EQ(expected_appt.uid, appt.uid); |
1346 | - EXPECT_EQ(expected_appt.color, appt.color); |
1347 | - EXPECT_EQ(expected_appt.summary, appt.summary); |
1348 | - EXPECT_EQ(1, appt.alarms.size()); |
1349 | - EXPECT_EQ(expected_alarms[i], appt.alarms[0]); |
1350 | - } |
1351 | - |
1352 | - |
1353 | - // cleanup |
1354 | - g_time_zone_unref(gtz); |
1355 | -} |
1356 | |
1357 | === removed directory 'tests/test-eds-valarms-config-files' |
1358 | === removed directory 'tests/test-eds-valarms-config-files/.config' |
1359 | === removed directory 'tests/test-eds-valarms-config-files/.config/evolution' |
1360 | === removed directory 'tests/test-eds-valarms-config-files/.config/evolution/sources' |
1361 | === removed file 'tests/test-eds-valarms-config-files/.config/evolution/sources/system-proxy.source' |
1362 | --- tests/test-eds-valarms-config-files/.config/evolution/sources/system-proxy.source 2015-04-06 00:19:01 +0000 |
1363 | +++ tests/test-eds-valarms-config-files/.config/evolution/sources/system-proxy.source 1970-01-01 00:00:00 +0000 |
1364 | @@ -1,21 +0,0 @@ |
1365 | - |
1366 | -[Data Source] |
1367 | -DisplayName=Default Proxy Settings |
1368 | -Enabled=true |
1369 | -Parent= |
1370 | - |
1371 | -[Proxy] |
1372 | -Method=default |
1373 | -IgnoreHosts=localhost;127.0.0.0/8;::1; |
1374 | -AutoconfigUrl= |
1375 | -FtpHost= |
1376 | -FtpPort=0 |
1377 | -HttpAuthPassword= |
1378 | -HttpAuthUser= |
1379 | -HttpHost= |
1380 | -HttpPort=8080 |
1381 | -HttpUseAuth=false |
1382 | -HttpsHost= |
1383 | -HttpsPort=0 |
1384 | -SocksHost= |
1385 | -SocksPort=0 |
1386 | |
1387 | === removed directory 'tests/test-eds-valarms-config-files/.local' |
1388 | === removed directory 'tests/test-eds-valarms-config-files/.local/share' |
1389 | === removed directory 'tests/test-eds-valarms-config-files/.local/share/evolution' |
1390 | === removed directory 'tests/test-eds-valarms-config-files/.local/share/evolution/calendar' |
1391 | === removed directory 'tests/test-eds-valarms-config-files/.local/share/evolution/calendar/system' |
1392 | === removed file 'tests/test-eds-valarms-config-files/.local/share/evolution/calendar/system/calendar.ics' |
1393 | --- tests/test-eds-valarms-config-files/.local/share/evolution/calendar/system/calendar.ics 2015-04-06 00:19:01 +0000 |
1394 | +++ tests/test-eds-valarms-config-files/.local/share/evolution/calendar/system/calendar.ics 1970-01-01 00:00:00 +0000 |
1395 | @@ -1,47 +0,0 @@ |
1396 | -BEGIN:VCALENDAR |
1397 | -CALSCALE:GREGORIAN |
1398 | -PRODID:-//Ximian//NONSGML Evolution Calendar//EN |
1399 | -VERSION:2.0 |
1400 | -X-EVOLUTION-DATA-REVISION:2015-04-05T21:32:47.354433Z(2) |
1401 | -BEGIN:VEVENT |
1402 | -UID:20150405T213247Z-4371-32011-1698-1@ubuntu-phablet |
1403 | -DTSTAMP:20150405T213247Z |
1404 | -DTSTART:20150424T183500Z |
1405 | -DTEND:20150424T193554Z |
1406 | -X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:Can't parse as RECUR value |
1407 | - in RRULE property. Removing entire property: ERROR: No Value |
1408 | -SUMMARY:London Sprint Flight |
1409 | -CREATED:20150405T213247Z |
1410 | -LAST-MODIFIED:20150405T213247Z |
1411 | -BEGIN:VALARM |
1412 | -X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-2@ubuntu-phablet |
1413 | -ACTION:AUDIO |
1414 | -TRIGGER;VALUE=DURATION;RELATED=START:-P1D |
1415 | -REPEAT:3 |
1416 | -DURATION:PT2M |
1417 | -END:VALARM |
1418 | -BEGIN:VALARM |
1419 | -X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-3@ubuntu-phablet |
1420 | -ACTION:DISPLAY |
1421 | -DESCRIPTION:Time to pack! |
1422 | -TRIGGER;VALUE=DURATION;RELATED=START:-P1D |
1423 | -REPEAT:3 |
1424 | -DURATION:PT2M |
1425 | -END:VALARM |
1426 | -BEGIN:VALARM |
1427 | -X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-5@ubuntu-phablet |
1428 | -ACTION:AUDIO |
1429 | -TRIGGER;VALUE=DURATION;RELATED=START:-PT3H |
1430 | -REPEAT:3 |
1431 | -DURATION:PT2M |
1432 | -END:VALARM |
1433 | -BEGIN:VALARM |
1434 | -X-EVOLUTION-ALARM-UID:20150405T213247Z-4371-32011-1698-6@ubuntu-phablet |
1435 | -ACTION:DISPLAY |
1436 | -DESCRIPTION:Go to the airport! |
1437 | -TRIGGER;VALUE=DURATION;RELATED=START:-PT3H |
1438 | -REPEAT:3 |
1439 | -DURATION:PT2M |
1440 | -END:VALARM |
1441 | -END:VEVENT |
1442 | -END:VCALENDAR |
There seems to be a small object leak, but otherwise I can only find faults in the EDS API :-)