Merge lp:~charlesk/indicator-datetime/lp-1440111-friendlier-calendar-items into lp:indicator-datetime/15.10

Proposed by Charles Kerr
Status: Merged
Approved by: Xavi Garcia
Approved revision: 440
Merged at revision: 433
Proposed branch: lp:~charlesk/indicator-datetime/lp-1440111-friendlier-calendar-items
Merge into: lp:indicator-datetime/15.10
Prerequisite: lp:~charlesk/indicator-datetime/lp-1474078-notification-blacklist-apps
Diff against target: 1141 lines (+339/-590)
10 files modified
debian/changelog (+6/-0)
debian/control (+1/-2)
src/settings-live.cpp (+2/-2)
src/snap.cpp (+6/-2)
tests/glib-fixture.h (+88/-0)
tests/libdbusmock-fixture.h (+155/-0)
tests/notification-fixture.h (+7/-47)
tests/test-notification.cpp (+73/-40)
tests/test-snap.cpp (+0/-396)
tests/test-sound.cpp (+1/-101)
To merge this branch: bzr merge lp:~charlesk/indicator-datetime/lp-1440111-friendlier-calendar-items
Reviewer Review Type Date Requested Status
Xavi Garcia Approve
PS Jenkins bot (community) continuous-integration Approve
David Barth Approve
Review via email: mp+284956@code.launchpad.net

This proposal supersedes a proposal from 2016-02-03.

Commit message

Corrects notifications' title and icon to show the correct information for calendar events.

Description of the change

Corrects notifications' title and icon to show the correct information for calendar events.

Based on <https://code.launchpad.net/~dbarth/indicator-datetime/adjust-title-notification-icons/+merge/284911> but stacked on top of a branch that's friendly to landing in vivid+xenial and adds unit tests for the change.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
435. By Charles Kerr

in settings-live.cpp, use std::string instead of auto to make g++ 4.9.2 happy on vivid

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
David Barth (dbarth) wrote :

Tested in silo 003, +1 for me

review: Approve
436. By Charles Kerr

in the GLib test Fixture, add helper functions to wait for arbitrary events and bus events

437. By Charles Kerr

add a DBusMock test Fixture with helper functions to wait for arbitrary bus method calls

438. By Charles Kerr

update notification tests to wait for the needed bus events instead of waiting for arbitrary time intervals

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
439. By Charles Kerr

in test-notifications we do need one wait() wart after all, because the Snap is building its impl proxies asynchronously and hasn't any public way of notifying when they're built

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
440. By Charles Kerr

resolve some test timing issues by deferring Snap object creation until it's needed

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

Looks good to me. Thanks Charles!

review: Approve
441. By Charles Kerr

merge lp:~stgraber/indicator-datetime/fix-deps

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 2016-01-29 18:53:46 +0000
3+++ debian/changelog 2016-03-10 16:21:24 +0000
4@@ -1,3 +1,9 @@
5+indicator-datetime (15.10+16.04.20160129-0ubuntu2) xenial; urgency=medium
6+
7+ * Don't pull systemd-shim on systems with systemd installed.
8+
9+ -- Stéphane Graber <stgraber@ubuntu.com> Wed, 24 Feb 2016 12:40:28 -0500
10+
11 indicator-datetime (15.10+16.04.20160129-0ubuntu1) xenial; urgency=medium
12
13 [ Charles Kerr ]
14
15=== modified file 'debian/control'
16--- debian/control 2016-03-10 16:21:24 +0000
17+++ debian/control 2016-03-10 16:21:24 +0000
18@@ -42,8 +42,7 @@
19 Depends: ${shlibs:Depends},
20 ${misc:Depends},
21 gsettings-ubuntu-schemas,
22- systemd-services,
23- systemd-shim,
24+ systemd | systemd-shim,
25 Recommends: indicator-applet | indicator-renderer,
26 evolution-data-server,
27 geoclue-ubuntu-geoip | geoclue-provider,
28
29=== modified file 'src/settings-live.cpp'
30--- src/settings-live.cpp 2016-03-10 16:21:24 +0000
31+++ src/settings-live.cpp 2016-03-10 16:21:24 +0000
32@@ -73,8 +73,8 @@
33 GVariantBuilder builder;
34 g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ss)"));
35 for(const auto& app : value){
36- const auto& pkgname {app.first};
37- const auto& appname {app.second};
38+ const std::string& pkgname {app.first};
39+ const std::string& appname {app.second};
40 g_variant_builder_add(&builder, "(ss)", pkgname.c_str(), appname.c_str());
41 }
42 g_settings_set_value(m_settings_cunh, SETTINGS_CUNH_BLACKLIST_S, g_variant_builder_end(&builder));
43
44=== modified file 'src/snap.cpp'
45--- src/snap.cpp 2016-03-10 16:21:24 +0000
46+++ src/snap.cpp 2016-03-10 16:21:24 +0000
47@@ -123,7 +123,7 @@
48 const auto minutes = std::chrono::minutes(m_settings->alarm_duration.get());
49 uin::Builder b;
50 b.set_body (appointment.summary);
51- b.set_icon_name ("alarm-clock");
52+ b.set_icon_name (appointment.is_ubuntu_alarm() ? "alarm-clock" : "reminder");
53 b.add_hint (uin::Builder::HINT_NONSHAPED_ICON);
54
55 const char * timefmt;
56@@ -137,7 +137,11 @@
57 timefmt = _("%a, %H:%M");
58 }
59 const auto timestr = appointment.begin.format(timefmt);
60- auto title = g_strdup_printf(_("Alarm %s"), timestr.c_str());
61+
62+ const auto titlefmt = appointment.is_ubuntu_alarm()
63+ ? _("Alarm %s")
64+ : _("Event %s");
65+ auto title = g_strdup_printf(titlefmt, timestr.c_str());
66 b.set_title (title);
67 g_free (title);
68 b.set_timeout (std::chrono::duration_cast<std::chrono::seconds>(minutes));
69
70=== modified file 'tests/glib-fixture.h'
71--- tests/glib-fixture.h 2015-09-09 16:16:41 +0000
72+++ tests/glib-fixture.h 2016-03-10 16:21:24 +0000
73@@ -20,7 +20,9 @@
74 #ifndef INDICATOR_DATETIME_TESTS_GLIB_FIXTURE_H
75 #define INDICATOR_DATETIME_TESTS_GLIB_FIXTURE_H
76
77+#include <functional> // std::function
78 #include <map>
79+#include <memory> // std::shared_ptr
80
81 #include <glib.h>
82 #include <glib/gstdio.h>
83@@ -109,6 +111,92 @@
84 g_source_remove(id);
85 }
86
87+ bool wait_for(std::function<bool()> test_function, guint timeout_msec=1000)
88+ {
89+ auto timer = std::shared_ptr<GTimer>(g_timer_new(), [](GTimer* t){g_timer_destroy(t);});
90+ const auto timeout_sec = timeout_msec / 1000.0;
91+ for (;;) {
92+ if (test_function())
93+ return true;
94+ //g_message("%f ... %f", g_timer_elapsed(timer.get(), nullptr), timeout_sec);
95+ if (g_timer_elapsed(timer.get(), nullptr) >= timeout_sec)
96+ return false;
97+ wait_msec();
98+ }
99+ }
100+
101+ bool wait_for_name_owned(GDBusConnection* connection,
102+ const gchar* name,
103+ guint timeout_msec=1000,
104+ GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
105+ {
106+ struct Data {
107+ GMainLoop* loop = nullptr;
108+ bool owned = false;
109+ };
110+ Data data;
111+
112+ auto on_name_appeared = [](GDBusConnection* /*connection*/,
113+ const gchar* /*name_*/,
114+ const gchar* name_owner,
115+ gpointer gdata)
116+ {
117+ if (name_owner == nullptr)
118+ return;
119+ auto tmp = static_cast<Data*>(gdata);
120+ tmp->owned = true;
121+ g_main_loop_quit(tmp->loop);
122+ };
123+
124+ const auto timeout_id = g_timeout_add(timeout_msec, wait_msec__timeout, loop);
125+ data.loop = loop;
126+ const auto watch_id = g_bus_watch_name_on_connection(connection,
127+ name,
128+ flags,
129+ on_name_appeared,
130+ nullptr, /* name_vanished */
131+ &data,
132+ nullptr); /* user_data_free_func */
133+ g_main_loop_run(loop);
134+
135+ g_bus_unwatch_name(watch_id);
136+ g_source_remove(timeout_id);
137+
138+ return data.owned;
139+ }
140+
141+ void EXPECT_NAME_OWNED_EVENTUALLY(GDBusConnection* connection,
142+ const gchar* name,
143+ guint timeout_msec=1000,
144+ GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
145+ {
146+ EXPECT_TRUE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name;
147+ }
148+
149+ void EXPECT_NAME_NOT_OWNED_EVENTUALLY(GDBusConnection* connection,
150+ const gchar* name,
151+ guint timeout_msec=1000,
152+ GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
153+ {
154+ EXPECT_FALSE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name;
155+ }
156+
157+ void ASSERT_NAME_OWNED_EVENTUALLY(GDBusConnection* connection,
158+ const gchar* name,
159+ guint timeout_msec=1000,
160+ GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
161+ {
162+ ASSERT_TRUE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name;
163+ }
164+
165+ void ASSERT_NAME_NOT_OWNED_EVENTUALLY(GDBusConnection* connection,
166+ const gchar* name,
167+ guint timeout_msec=1000,
168+ GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
169+ {
170+ ASSERT_FALSE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name;
171+ }
172+
173 GMainLoop * loop;
174 };
175
176
177=== added file 'tests/libdbusmock-fixture.h'
178--- tests/libdbusmock-fixture.h 1970-01-01 00:00:00 +0000
179+++ tests/libdbusmock-fixture.h 2016-03-10 16:21:24 +0000
180@@ -0,0 +1,155 @@
181+/*
182+ * Copyright 2014-2016 Canonical Ltd.
183+ *
184+ * This program is free software: you can redistribute it and/or modify it
185+ * under the terms of the GNU General Public License version 3, as published
186+ * by the Free Software Foundation.
187+ *
188+ * This program is distributed in the hope that it will be useful, but
189+ * WITHOUT ANY WARRANTY; without even the implied warranties of
190+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
191+ * PURPOSE. See the GNU General Public License for more details.
192+ *
193+ * You should have received a copy of the GNU General Public License along
194+ * with this program. If not, see <http://www.gnu.org/licenses/>.
195+ *
196+ * Authors:
197+ * Charles Kerr <charles.kerr@canonical.com>
198+ */
199+
200+#pragma once
201+
202+#include "glib-fixture.h"
203+
204+#include <libdbustest/dbus-test.h>
205+
206+/***
207+****
208+***/
209+
210+class LibdbusmockFixture: public GlibFixture
211+{
212+private:
213+
214+ typedef GlibFixture super;
215+
216+protected:
217+
218+ GDBusConnection * system_bus {};
219+ GDBusConnection * session_bus {};
220+ DbusTestService * service {};
221+
222+ void SetUp() override
223+ {
224+
225+ super::SetUp();
226+
227+ service = dbus_test_service_new(nullptr);
228+ }
229+
230+ void startDbusMock()
231+ {
232+ // start 'em up.
233+ // make the system bus work off the mock bus too, since that's
234+ // where the upower and screen are on the system bus...
235+
236+ dbus_test_service_start_tasks(service);
237+ g_setenv("DBUS_SYSTEM_BUS_ADDRESS", g_getenv("DBUS_SESSION_BUS_ADDRESS"), TRUE);
238+
239+ session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
240+ ASSERT_NE(nullptr, session_bus);
241+ g_dbus_connection_set_exit_on_close(session_bus, false);
242+ g_object_add_weak_pointer(G_OBJECT(session_bus), (gpointer *)&session_bus);
243+
244+ system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr);
245+ ASSERT_NE(nullptr, system_bus);
246+ g_dbus_connection_set_exit_on_close(system_bus, FALSE);
247+ g_object_add_weak_pointer(G_OBJECT(system_bus), (gpointer *)&system_bus);
248+ }
249+
250+ void TearDown() override
251+ {
252+ g_clear_object(&service);
253+ g_object_unref(session_bus);
254+ g_object_unref(system_bus);
255+
256+ // wait a little while for the scaffolding to shut down,
257+ // but don't block on it forever...
258+ unsigned int cleartry = 0;
259+ while (((system_bus != nullptr) || (session_bus != nullptr)) && (cleartry < 50))
260+ {
261+ g_usleep(100000);
262+ while (g_main_pending())
263+ g_main_iteration(true);
264+ cleartry++;
265+ }
266+
267+ super::TearDown();
268+ }
269+
270+ bool wait_for_method_call(DbusTestDbusMock* mock,
271+ DbusTestDbusMockObject* obj,
272+ const gchar* method,
273+ GVariant* params=nullptr,
274+ guint timeout_msec=100)
275+ {
276+ if (params != nullptr)
277+ g_variant_ref_sink(params);
278+
279+ auto test_function = [mock, obj, method, params]() {
280+ GError* error {};
281+ const auto called = dbus_test_dbus_mock_object_check_method_call(mock,
282+ obj,
283+ method,
284+ params,
285+ &error);
286+ if (error != nullptr) {
287+ g_critical("Error looking for method call '%s': %s", method, error->message);
288+ g_clear_error(&error);
289+ }
290+
291+ return called;
292+ };
293+
294+ const auto ret = wait_for(test_function, timeout_msec);
295+ g_clear_pointer(&params, g_variant_unref);
296+ return ret;
297+ }
298+
299+ void EXPECT_METHOD_CALLED_EVENTUALLY(DbusTestDbusMock* mock,
300+ DbusTestDbusMockObject* obj,
301+ const gchar* method,
302+ GVariant* params=nullptr,
303+ guint timeout_msec=1000)
304+ {
305+ EXPECT_TRUE(wait_for_method_call(mock, obj, method, params, timeout_msec)) << "method: " << method;
306+ }
307+
308+ void EXPECT_METHOD_NOT_CALLED_EVENTUALLY(DbusTestDbusMock* mock,
309+ DbusTestDbusMockObject* obj,
310+ const gchar* method,
311+ GVariant* params=nullptr,
312+ guint timeout_msec=1000)
313+ {
314+ EXPECT_FALSE(wait_for_method_call(mock, obj, method, params, timeout_msec)) << "method: " << method;
315+ }
316+
317+ void ASSERT_METHOD_CALLED_EVENTUALLY(DbusTestDbusMock* mock,
318+ DbusTestDbusMockObject* obj,
319+ const gchar* method,
320+ GVariant* params=nullptr,
321+ guint timeout_msec=1000)
322+ {
323+ ASSERT_TRUE(wait_for_method_call(mock, obj, method, params, timeout_msec)) << "method: " << method;
324+ }
325+
326+ void ASSERT_METHOD_NOT_CALLED_EVENTUALLY(DbusTestDbusMock* mock,
327+ DbusTestDbusMockObject* obj,
328+ const gchar* method,
329+ GVariant* params=nullptr,
330+ guint timeout_msec=1000)
331+ {
332+ ASSERT_FALSE(wait_for_method_call(mock, obj, method, params, timeout_msec)) << "method: " << method;
333+ }
334+};
335+
336
337=== modified file 'tests/notification-fixture.h'
338--- tests/notification-fixture.h 2016-03-10 16:21:24 +0000
339+++ tests/notification-fixture.h 2016-03-10 16:21:24 +0000
340@@ -19,7 +19,7 @@
341
342 #pragma once
343
344-#include "glib-fixture.h"
345+#include "libdbusmock-fixture.h"
346
347 #include <datetime/appointment.h>
348 #include <datetime/dbus-shared.h>
349@@ -38,24 +38,18 @@
350 ****
351 ***/
352
353-//using namespace unity::indicator::datetime;
354-
355-class NotificationFixture: public GlibFixture
356+class NotificationFixture: public LibdbusmockFixture
357 {
358 private:
359
360- typedef GlibFixture super;
361+ typedef LibdbusmockFixture super;
362+
363+protected:
364
365 static constexpr char const * NOTIFY_BUSNAME {"org.freedesktop.Notifications"};
366 static constexpr char const * NOTIFY_INTERFACE {"org.freedesktop.Notifications"};
367 static constexpr char const * NOTIFY_PATH {"/org/freedesktop/Notifications"};
368
369- //namespace uin = unity::indicator::notifications;
370-
371- //using namespace unity::indicator::datetime;
372-
373-protected:
374-
375 static constexpr char const * HAPTIC_METHOD_VIBRATE_PATTERN {"VibratePattern"};
376
377 static constexpr int SCREEN_COOKIE {8675309};
378@@ -90,9 +84,7 @@
379
380 unity::indicator::datetime::Appointment appt;
381 unity::indicator::datetime::Appointment ualarm;
382- GDBusConnection * system_bus = nullptr;
383- GDBusConnection * session_bus = nullptr;
384- DbusTestService * service = nullptr;
385+
386 DbusTestDbusMock * as_mock = nullptr;
387 DbusTestDbusMock * notify_mock = nullptr;
388 DbusTestDbusMock * powerd_mock = nullptr;
389@@ -131,8 +123,6 @@
390 ualarm.end = tomorrow;
391 ualarm.alarms.push_back(unity::indicator::datetime::Alarm{"It's Tomorrow!", "", appt.begin});
392
393- service = dbus_test_service_new(nullptr);
394-
395 ///
396 /// Add the AccountsService mock
397 ///
398@@ -308,23 +298,7 @@
399 g_assert_no_error (error);
400 dbus_test_service_add_task(service, DBUS_TEST_TASK(haptic_mock));
401
402-
403- // start 'em up.
404- // make the system bus work off the mock bus too, since that's
405- // where the upower and screen are on the system bus...
406-
407- dbus_test_service_start_tasks(service);
408- g_setenv("DBUS_SYSTEM_BUS_ADDRESS", g_getenv("DBUS_SESSION_BUS_ADDRESS"), TRUE);
409-
410- session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
411- ASSERT_NE(nullptr, session_bus);
412- g_dbus_connection_set_exit_on_close(session_bus, false);
413- g_object_add_weak_pointer(G_OBJECT(session_bus), (gpointer *)&session_bus);
414-
415- system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr);
416- ASSERT_NE(nullptr, system_bus);
417- g_dbus_connection_set_exit_on_close(system_bus, FALSE);
418- g_object_add_weak_pointer(G_OBJECT(system_bus), (gpointer *)&system_bus);
419+ startDbusMock();
420 }
421
422 void TearDown() override
423@@ -334,20 +308,6 @@
424 g_clear_object(&powerd_mock);
425 g_clear_object(&notify_mock);
426 g_clear_object(&as_mock);
427- g_clear_object(&service);
428- g_object_unref(session_bus);
429- g_object_unref(system_bus);
430-
431- // wait a little while for the scaffolding to shut down,
432- // but don't block on it forever...
433- unsigned int cleartry = 0;
434- while (((system_bus != nullptr) || (session_bus != nullptr)) && (cleartry < 50))
435- {
436- g_usleep(100000);
437- while (g_main_pending())
438- g_main_iteration(true);
439- cleartry++;
440- }
441
442 super::TearDown();
443 }
444
445=== modified file 'tests/test-notification.cpp'
446--- tests/test-notification.cpp 2016-03-10 16:21:24 +0000
447+++ tests/test-notification.cpp 2016-03-10 16:21:24 +0000
448@@ -37,7 +37,7 @@
449 {
450 g_main_loop_quit(static_cast<GMainLoop*>(gloop));
451 return G_SOURCE_REMOVE;
452- };
453+ }
454 }
455
456 /***
457@@ -58,11 +58,13 @@
458 // combinatorial factor #1: event type
459 struct {
460 Appointment appt;
461+ const char* icon_name;
462+ const char* prefix;
463 bool expected_notify_called;
464 bool expected_vibrate_called;
465 } test_appts[] = {
466- { appt, true, true },
467- { ualarm, true, true }
468+ { appt, "reminder", "Event", true, true },
469+ { ualarm, "alarm-clock", "Alarm", true, true }
470 };
471
472 // combinatorial factor #2: indicator-datetime's haptic mode
473@@ -90,11 +92,13 @@
474 const std::set<std::pair<std::string,std::string>> blacklist_empty;
475 struct {
476 std::set<std::pair<std::string,std::string>> muted_apps; // apps that should not trigger notifications
477- bool expected_notify_called; // do we expect the notification tho show?
478- bool expected_vibrate_called; // do we expect the phone to vibrate?
479+ std::set<Appointment::Type> expected_notify_called; // do we expect the notification to show?
480+ std::set<Appointment::Type> expected_vibrate_called; // do we expect the phone to vibrate?
481 } test_muted_apps[] = {
482- { blacklist_calendar, false, false },
483- { blacklist_empty, true, true }
484+ { blacklist_empty, std::set<Appointment::Type>{ Appointment::Type::UBUNTU_ALARM, Appointment::Type::EVENT },
485+ std::set<Appointment::Type>{ Appointment::Type::UBUNTU_ALARM, Appointment::Type::EVENT } },
486+ { blacklist_calendar, std::set<Appointment::Type>{ Appointment::Type::UBUNTU_ALARM },
487+ std::set<Appointment::Type>{ Appointment::Type::UBUNTU_ALARM } }
488 };
489
490 for (const auto& test_appt : test_appts)
491@@ -105,57 +109,86 @@
492 {
493 for (const auto& test_muted : test_muted_apps)
494 {
495- auto snap = create_snap(ne, sb, settings);
496-
497 const bool expected_notify_called = test_appt.expected_notify_called
498 && test_vibes.expected_notify_called
499- && test_muted.expected_notify_called
500+ && (test_muted.expected_notify_called.count(test_appt.appt.type) > 0)
501 && test_haptic.expected_notify_called;
502
503 const bool expected_vibrate_called = test_appt.expected_vibrate_called
504 && test_vibes.expected_vibrate_called
505- && test_muted.expected_vibrate_called
506+ && (test_muted.expected_vibrate_called.count(test_appt.appt.type) > 0)
507 && test_haptic.expected_vibrate_called;
508
509- // clear out any previous iterations' noise
510- GError * error = nullptr;
511- dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error);
512- g_assert_no_error(error);
513- dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error);
514- g_assert_no_error(error);
515-
516- // set the properties to match the test case
517+ // set test case properties: blacklist
518 settings->muted_apps.set(test_muted.muted_apps);
519+
520+ // set test case properties: haptic mode
521 settings->alarm_haptic.set(test_haptic.haptic_mode);
522+
523+ // set test case properties: other-vibrations flag
524+ // (and wait for the PropertiesChanged signal so we know the dbusmock got it)
525+ GError * error {};
526 dbus_test_dbus_mock_object_update_property(as_mock,
527 as_obj,
528 PROP_OTHER_VIBRATIONS,
529 g_variant_new_boolean(test_vibes.other_vibrations),
530 &error);
531 g_assert_no_error(error);
532- wait_msec(100);
533+
534+ // wait for previous iterations' bus noise to finish and reset the counters
535+ wait_msec(500);
536+ dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error);
537+ dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error);
538+ g_assert_no_error(error);
539
540 // run the test
541- (*snap)(appt, appt.alarms.front(), func, func);
542- wait_msec(100);
543-
544- // test that the notification was as expected
545- const bool notify_called = dbus_test_dbus_mock_object_check_method_call(notify_mock,
546- notify_obj,
547- METHOD_NOTIFY,
548- nullptr,
549- &error);
550- g_assert_no_error(error);
551- EXPECT_EQ(expected_notify_called, notify_called);
552-
553- // test that the vibration was as expected
554- const bool vibrate_called = dbus_test_dbus_mock_object_check_method_call(haptic_mock,
555- haptic_obj,
556- HAPTIC_METHOD_VIBRATE_PATTERN,
557- nullptr,
558- &error);
559- g_assert_no_error(error);
560- EXPECT_EQ(expected_vibrate_called, vibrate_called);
561+ auto snap = create_snap(ne, sb, settings);
562+ (*snap)(test_appt.appt, appt.alarms.front(), func, func);
563+
564+ // confirm that the notification was as expected
565+ if (expected_notify_called) {
566+ EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY);
567+ } else {
568+ EXPECT_METHOD_NOT_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY);
569+ }
570+
571+ // confirm that the vibration was as expected
572+ if (expected_vibrate_called) {
573+ EXPECT_METHOD_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE_PATTERN);
574+ } else {
575+ EXPECT_METHOD_NOT_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE_PATTERN);
576+ }
577+
578+ // confirm that the notification was as expected
579+ guint num_notify_calls = 0;
580+ const auto notify_calls = dbus_test_dbus_mock_object_get_method_calls(notify_mock,
581+ notify_obj,
582+ METHOD_NOTIFY,
583+ &num_notify_calls,
584+ &error);
585+ g_assert_no_error(error);
586+ if (num_notify_calls > 0)
587+ {
588+ // test that Notify was called with the app_name
589+ const gchar* app_name {nullptr};
590+ g_variant_get_child(notify_calls[0].params, 0, "&s", &app_name);
591+ ASSERT_STREQ(APP_NAME, app_name);
592+
593+ // test that Notify was called with the type-appropriate icon
594+ const gchar* icon_name {nullptr};
595+ g_variant_get_child(notify_calls[0].params, 2, "&s", &icon_name);
596+ ASSERT_STREQ(test_appt.icon_name, icon_name);
597+
598+ // test that the Notification title has the correct prefix
599+ const gchar* title {nullptr};
600+ g_variant_get_child(notify_calls[0].params, 3, "&s", &title);
601+ ASSERT_TRUE(g_str_has_prefix(title, test_appt.prefix));
602+
603+ // test that Notify was called with the appointment's body
604+ const gchar* body {nullptr};
605+ g_variant_get_child(notify_calls[0].params, 4, "&s", &body);
606+ ASSERT_STREQ(test_appt.appt.summary.c_str(), body);
607+ }
608 }
609 }
610 }
611
612=== removed file 'tests/test-snap.cpp'
613--- tests/test-snap.cpp 2016-03-10 16:21:24 +0000
614+++ tests/test-snap.cpp 1970-01-01 00:00:00 +0000
615@@ -1,396 +0,0 @@
616-/*
617- * Copyright 2014 Canonical Ltd.
618- *
619- * Authors:
620- * Charles Kerr <charles.kerr@canonical.com>
621- *
622- * This program is free software: you can redistribute it and/or modify it
623- * under the terms of the GNU General Public License version 3, as published
624- * by the Free Software Foundation.
625- *
626- * This program is distributed in the hope that it will be useful, but
627- * WITHOUT ANY WARRANTY; without even the implied warranties of
628- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
629- * PURPOSE. See the GNU General Public License for more details.
630- *
631- * You should have received a copy of the GNU General Public License along
632- * with this program. If not, see <http://www.gnu.org/licenses/>.
633- */
634-
635-#include <datetime/appointment.h>
636-#include <datetime/dbus-shared.h>
637-#include <datetime/settings.h>
638-#include <datetime/snap.h>
639-
640-#include <notifications/dbus-shared.h>
641-#include <notifications/notifications.h>
642-
643-#include "notification-fixture.h"
644-
645-using namespace unity::indicator::datetime;
646-
647-namespace uin = unity::indicator::notifications;
648-
649-/***
650-****
651-***/
652-
653-namespace
654-{
655- static constexpr char const * APP_NAME {"indicator-datetime-service"};
656-}
657-
658-using namespace unity::indicator::datetime;
659-
660-/***
661-****
662-***/
663-
664-namespace
665-{
666- gboolean quit_idle (gpointer gloop)
667- {
668- g_main_loop_quit(static_cast<GMainLoop*>(gloop));
669- return G_SOURCE_REMOVE;
670- };
671-}
672-
673-TEST_F(NotificationFixture, InteractiveDuration)
674-{
675- static constexpr int duration_minutes = 120;
676- auto settings = std::make_shared<Settings>();
677- settings->alarm_duration.set(duration_minutes);
678- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
679- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
680- auto snap = create_snap(ne, sb, settings);
681-
682- make_interactive();
683-
684- // call the Snap Decision
685- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
686- (*snap)(appt, appt.alarms.front(), func, func);
687-
688- // confirm that Notify got called once
689- guint len = 0;
690- GError * error = nullptr;
691- const auto calls = dbus_test_dbus_mock_object_get_method_calls (notify_mock,
692- notify_obj,
693- METHOD_NOTIFY,
694- &len,
695- &error);
696- g_assert_no_error(error);
697- ASSERT_EQ(1, len);
698-
699- // confirm that the app_name passed to Notify was APP_NAME
700- const auto& params = calls[0].params;
701- ASSERT_EQ(8, g_variant_n_children(params));
702- const char * str = nullptr;
703- g_variant_get_child (params, 0, "&s", &str);
704- ASSERT_STREQ(APP_NAME, str);
705-
706- // confirm that the icon passed to Notify was "alarm-clock"
707- g_variant_get_child (params, 2, "&s", &str);
708- ASSERT_STREQ("alarm-clock", str);
709-
710- // confirm that the hints passed to Notify included a timeout matching duration_minutes
711- int32_t i32;
712- bool b;
713- auto hints = g_variant_get_child_value (params, 6);
714- b = g_variant_lookup (hints, HINT_TIMEOUT, "i", &i32);
715- EXPECT_TRUE(b);
716- const auto duration = std::chrono::minutes(duration_minutes);
717- EXPECT_EQ(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(), i32);
718- g_variant_unref(hints);
719- ne.reset();
720-}
721-
722-/***
723-****
724-***/
725-
726-TEST_F(NotificationFixture, InhibitSleep)
727-{
728- auto settings = std::make_shared<Settings>();
729- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
730- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
731- auto snap = create_snap(ne, sb, settings);
732-
733- make_interactive();
734-
735- // invoke the notification
736- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
737- (*snap)(appt, appt.alarms.front(), func, func);
738-
739- wait_msec(1000);
740-
741- // confirm that sleep got inhibited
742- GError * error = nullptr;
743- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
744- powerd_obj,
745- POWERD_METHOD_REQUEST_SYS_STATE,
746- g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE),
747- &error));
748-
749- // confirm that the screen got forced on
750- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock,
751- screen_obj,
752- SCREEN_METHOD_KEEP_DISPLAY_ON,
753- nullptr,
754- &error));
755-
756- // force-close the snap
757- wait_msec(100);
758- snap.reset();
759- wait_msec(100);
760-
761- // confirm that sleep got uninhibted
762- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
763- powerd_obj,
764- POWERD_METHOD_CLEAR_SYS_STATE,
765- g_variant_new("(s)", POWERD_COOKIE),
766- &error));
767-
768- // confirm that the screen's no longer forced on
769- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock,
770- screen_obj,
771- SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST,
772- g_variant_new("(i)", SCREEN_COOKIE),
773- &error));
774-
775- g_assert_no_error (error);
776-}
777-
778-/***
779-****
780-***/
781-
782-TEST_F(NotificationFixture, ForceScreen)
783-{
784- auto settings = std::make_shared<Settings>();
785- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
786- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
787- auto snap = create_snap(ne, sb, settings);
788-
789- make_interactive();
790-
791- // invoke the notification
792- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
793- (*snap)(appt, appt.alarms.front(), func, func);
794-
795- wait_msec(1000);
796-
797- // confirm that sleep got inhibited
798- GError * error = nullptr;
799- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
800- powerd_obj,
801- POWERD_METHOD_REQUEST_SYS_STATE,
802- g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE),
803- &error));
804- g_assert_no_error(error);
805-
806- // force-close the snap
807- wait_msec(100);
808- snap.reset();
809- wait_msec(100);
810-
811- // confirm that sleep got uninhibted
812- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
813- powerd_obj,
814- POWERD_METHOD_CLEAR_SYS_STATE,
815- g_variant_new("(s)", POWERD_COOKIE),
816- &error));
817- g_assert_no_error(error);
818-}
819-
820-/***
821-****
822-***/
823-
824-/**
825- * A DefaultSoundBuilder wrapper which remembers the parameters of the last sound created.
826- */
827-class TestSoundBuilder: public uin::SoundBuilder
828-{
829-public:
830- TestSoundBuilder() =default;
831- ~TestSoundBuilder() =default;
832-
833- virtual std::shared_ptr<uin::Sound> create(const std::string& role, const std::string& uri, unsigned int volume, bool loop) override {
834- m_role = role;
835- m_uri = uri;
836- m_volume = volume;
837- m_loop = loop;
838- return m_impl.create(role, uri, volume, loop);
839- }
840-
841- const std::string& role() { return m_role; }
842- const std::string& uri() { return m_uri; }
843- unsigned int volume() { return m_volume; }
844- bool loop() { return m_loop; }
845-
846-private:
847- std::string m_role;
848- std::string m_uri;
849- unsigned int m_volume;
850- bool m_loop;
851- uin::DefaultSoundBuilder m_impl;
852-};
853-
854-std::string path_to_uri(const std::string& path)
855-{
856- auto file = g_file_new_for_path(path.c_str());
857- auto uri_cstr = g_file_get_uri(file);
858- std::string uri = uri_cstr;
859- g_free(uri_cstr);
860- g_clear_pointer(&file, g_object_unref);
861- return uri;
862-}
863-
864-TEST_F(NotificationFixture,DefaultSounds)
865-{
866- auto settings = std::make_shared<Settings>();
867- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
868- auto sb = std::make_shared<TestSoundBuilder>();
869- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
870-
871- const struct {
872- Appointment appointment;
873- std::string expected_role;
874- std::string expected_uri;
875- } test_cases[] = {
876- { ualarm, "alarm", path_to_uri(ALARM_DEFAULT_SOUND) },
877- { appt, "alert", path_to_uri(CALENDAR_DEFAULT_SOUND) }
878- };
879-
880- auto snap = create_snap(ne, sb, settings);
881-
882- for(const auto& test_case : test_cases)
883- {
884- (*snap)(test_case.appointment, test_case.appointment.alarms.front(), func, func);
885- wait_msec(100);
886- EXPECT_EQ(test_case.expected_uri, sb->uri());
887- EXPECT_EQ(test_case.expected_role, sb->role());
888- }
889-}
890-
891-/***
892-****
893-***/
894-
895-TEST_F(NotificationFixture,Notification)
896-{
897- // Feed different combinations of system settings,
898- // indicator-datetime settings, and event types,
899- // then see if notifications and haptic feedback behave as expected.
900-
901- auto settings = std::make_shared<Settings>();
902- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
903- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
904- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
905-
906- // combinatorial factor #1: event type
907- struct {
908- Appointment appt;
909- bool expected_notify_called;
910- bool expected_vibrate_called;
911- } test_appts[] = {
912- { appt, true, true },
913- { ualarm, true, true }
914- };
915-
916- // combinatorial factor #2: indicator-datetime's haptic mode
917- struct {
918- const char* haptic_mode;
919- bool expected_notify_called;
920- bool expected_vibrate_called;
921- } test_haptics[] = {
922- { "none", true, false },
923- { "pulse", true, true }
924- };
925-
926- // combinatorial factor #3: system settings' "other vibrations" enabled
927- struct {
928- bool other_vibrations;
929- bool expected_notify_called;
930- bool expected_vibrate_called;
931- } test_other_vibrations[] = {
932- { true, true, true },
933- { false, true, false }
934- };
935-
936- // combinatorial factor #4: system settings' notifications app blacklist
937- const std::set<std::pair<std::string,std::string>> blacklist_calendar { std::make_pair(std::string{"com.ubuntu.calendar"}, std::string{"calendar-app"}) };
938- const std::set<std::pair<std::string,std::string>> blacklist_empty;
939- struct {
940- std::set<std::pair<std::string,std::string>> muted_apps; // apps that should not trigger notifications
941- bool expected_notify_called; // do we expect the notification tho show?
942- bool expected_vibrate_called; // do we expect the phone to vibrate?
943- } test_muted_apps[] = {
944- { blacklist_calendar, false, false },
945- { blacklist_empty, true, true }
946- };
947-
948- for (const auto& test_appt : test_appts)
949- {
950- for (const auto& test_haptic : test_haptics)
951- {
952- for (const auto& test_vibes : test_other_vibrations)
953- {
954- for (const auto& test_muted : test_muted_apps)
955- {
956- auto snap = create_snap(ne, sb, settings);
957-
958- const bool expected_notify_called = test_appt.expected_notify_called
959- && test_vibes.expected_notify_called
960- && test_muted.expected_notify_called
961- && test_haptic.expected_notify_called;
962-
963- const bool expected_vibrate_called = test_appt.expected_vibrate_called
964- && test_vibes.expected_vibrate_called
965- && test_muted.expected_vibrate_called
966- && test_haptic.expected_vibrate_called;
967-
968- // clear out any previous iterations' noise
969- GError * error = nullptr;
970- dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error);
971- g_assert_no_error(error);
972- dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error);
973- g_assert_no_error(error);
974-
975- // set the properties to match the test case
976- settings->muted_apps.set(test_muted.muted_apps);
977- settings->alarm_haptic.set(test_haptic.haptic_mode);
978- dbus_test_dbus_mock_object_update_property(as_mock,
979- as_obj,
980- PROP_OTHER_VIBRATIONS,
981- g_variant_new_boolean(test_vibes.other_vibrations),
982- &error);
983- g_assert_no_error(error);
984- wait_msec(100);
985-
986- // run the test
987- (*snap)(appt, appt.alarms.front(), func, func);
988- wait_msec(100);
989-
990- // test that the notification was as expected
991- const bool notify_called = dbus_test_dbus_mock_object_check_method_call(notify_mock,
992- notify_obj,
993- METHOD_NOTIFY,
994- nullptr,
995- &error);
996- g_assert_no_error(error);
997- EXPECT_EQ(expected_notify_called, notify_called);
998-
999- // test that the vibration was as expected
1000- const bool vibrate_called = dbus_test_dbus_mock_object_check_method_call(haptic_mock,
1001- haptic_obj,
1002- HAPTIC_METHOD_VIBRATE_PATTERN,
1003- nullptr,
1004- &error);
1005- g_assert_no_error(error);
1006- EXPECT_EQ(expected_vibrate_called, vibrate_called);
1007- }
1008- }
1009- }
1010- }
1011-}
1012
1013=== modified file 'tests/test-sound.cpp'
1014--- tests/test-sound.cpp 2016-03-10 16:21:24 +0000
1015+++ tests/test-sound.cpp 2016-03-10 16:21:24 +0000
1016@@ -85,7 +85,7 @@
1017
1018 // confirm that the icon passed to Notify was "alarm-clock"
1019 g_variant_get_child (params, 2, "&s", &str);
1020- ASSERT_STREQ("alarm-clock", str);
1021+ ASSERT_STREQ("reminder", str);
1022
1023 // confirm that the hints passed to Notify included a timeout matching duration_minutes
1024 int32_t i32;
1025@@ -103,104 +103,6 @@
1026 ****
1027 ***/
1028
1029-TEST_F(NotificationFixture, InhibitSleep)
1030-{
1031- auto settings = std::make_shared<Settings>();
1032- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
1033- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
1034- auto snap = create_snap(ne, sb, settings);
1035-
1036- make_interactive();
1037-
1038- // invoke the notification
1039- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
1040- (*snap)(appt, appt.alarms.front(), func, func);
1041-
1042- wait_msec(1000);
1043-
1044- // confirm that sleep got inhibited
1045- GError * error = nullptr;
1046- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
1047- powerd_obj,
1048- POWERD_METHOD_REQUEST_SYS_STATE,
1049- g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE),
1050- &error));
1051-
1052- // confirm that the screen got forced on
1053- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock,
1054- screen_obj,
1055- SCREEN_METHOD_KEEP_DISPLAY_ON,
1056- nullptr,
1057- &error));
1058-
1059- // force-close the snap
1060- wait_msec(100);
1061- snap.reset();
1062- wait_msec(100);
1063-
1064- // confirm that sleep got uninhibted
1065- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
1066- powerd_obj,
1067- POWERD_METHOD_CLEAR_SYS_STATE,
1068- g_variant_new("(s)", POWERD_COOKIE),
1069- &error));
1070-
1071- // confirm that the screen's no longer forced on
1072- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock,
1073- screen_obj,
1074- SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST,
1075- g_variant_new("(i)", SCREEN_COOKIE),
1076- &error));
1077-
1078- g_assert_no_error (error);
1079-}
1080-
1081-/***
1082-****
1083-***/
1084-
1085-TEST_F(NotificationFixture, ForceScreen)
1086-{
1087- auto settings = std::make_shared<Settings>();
1088- auto ne = std::make_shared<unity::indicator::notifications::Engine>(APP_NAME);
1089- auto sb = std::make_shared<unity::indicator::notifications::DefaultSoundBuilder>();
1090- auto snap = create_snap(ne, sb, settings);
1091-
1092- make_interactive();
1093-
1094- // invoke the notification
1095- auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);};
1096- (*snap)(appt, appt.alarms.front(), func, func);
1097-
1098- wait_msec(1000);
1099-
1100- // confirm that sleep got inhibited
1101- GError * error = nullptr;
1102- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
1103- powerd_obj,
1104- POWERD_METHOD_REQUEST_SYS_STATE,
1105- g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE),
1106- &error));
1107- g_assert_no_error(error);
1108-
1109- // force-close the snap
1110- wait_msec(100);
1111- snap.reset();
1112- wait_msec(100);
1113-
1114- // confirm that sleep got uninhibted
1115- EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock,
1116- powerd_obj,
1117- POWERD_METHOD_CLEAR_SYS_STATE,
1118- g_variant_new("(s)", POWERD_COOKIE),
1119- &error));
1120- g_assert_no_error(error);
1121-}
1122-
1123-/***
1124-****
1125-***/
1126-
1127 /**
1128 * A DefaultSoundBuilder wrapper which remembers the parameters of the last sound created.
1129 */
1130@@ -258,11 +160,9 @@
1131 };
1132
1133 auto snap = create_snap(ne, sb, settings);
1134-
1135 for(const auto& test_case : test_cases)
1136 {
1137 (*snap)(test_case.appointment, test_case.appointment.alarms.front(), func, func);
1138- wait_msec(100);
1139 EXPECT_EQ(test_case.expected_uri, sb->uri());
1140 EXPECT_EQ(test_case.expected_role, sb->role());
1141 }

Subscribers

People subscribed via source and target branches