aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/libdbusmock-fixture.h9
-rw-r--r--tests/test-notification-response.cpp144
-rw-r--r--tests/test-notification.cpp100
4 files changed, 146 insertions, 108 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b7f60bb..3bc6777 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -50,6 +50,7 @@ add_test_by_name(test-datetime)
if(HAVE_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS)
add_test_by_name(test-sound)
add_test_by_name(test-notification)
+add_test_by_name(test-notification-response)
endif()
add_test_by_name(test-actions)
add_test_by_name(test-alarm-queue)
diff --git a/tests/libdbusmock-fixture.h b/tests/libdbusmock-fixture.h
index 14eab8f..7301042 100644
--- a/tests/libdbusmock-fixture.h
+++ b/tests/libdbusmock-fixture.h
@@ -75,14 +75,7 @@ protected:
// wait a little while for the scaffolding to shut down,
// but don't block on it forever...
- unsigned int cleartry = 0;
- while (((system_bus != nullptr) || (session_bus != nullptr)) && (cleartry < 50))
- {
- g_usleep(100000);
- while (g_main_pending())
- g_main_iteration(true);
- cleartry++;
- }
+ wait_for([this](){return system_bus==nullptr && session_bus==nullptr;}, 5000);
super::TearDown();
}
diff --git a/tests/test-notification-response.cpp b/tests/test-notification-response.cpp
new file mode 100644
index 0000000..fd40ed8
--- /dev/null
+++ b/tests/test-notification-response.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2014-2016 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ */
+
+#include <datetime/appointment.h>
+#include <datetime/settings.h>
+#include <datetime/snap.h>
+
+#include "notification-fixture.h"
+
+/***
+****
+***/
+
+using namespace ayatana::indicator::datetime;
+
+namespace
+{
+ static constexpr char const * APP_NAME {"indicator-datetime-service"};
+
+ gboolean quit_idle (gpointer gloop)
+ {
+ g_main_loop_quit(static_cast<GMainLoop*>(gloop));
+ return G_SOURCE_REMOVE;
+ }
+}
+
+/***
+****
+***/
+
+TEST_F(NotificationFixture,Response)
+{
+ // create the world
+ make_interactive();
+ auto ne = std::make_shared<ayatana::indicator::notifications::Engine>(APP_NAME);
+ auto sb = std::make_shared<ayatana::indicator::notifications::DefaultSoundBuilder>();
+ auto settings = std::make_shared<Settings>();
+ int next_notification_id {FIRST_NOTIFY_ID};
+
+ // set a response callback that remembers what response we got
+ bool on_response_called {};
+ Snap::Response response {};
+ auto on_response = [this, &on_response_called, &response]
+ (const Appointment&, const Alarm&, const Snap::Response& r){
+ on_response_called = true;
+ response = r;
+ g_idle_add(quit_idle, loop);
+ };
+
+ // our tests!
+ const struct {
+ Appointment appt;
+ std::vector<std::string> expected_actions;
+ std::string action;
+ Snap::Response expected_response;
+ } tests[] = {
+ { appt, {"show-app"}, "show-app", Snap::Response::ShowApp },
+ { ualarm, {"none", "snooze"}, "snooze", Snap::Response::Snooze },
+ { ualarm, {"none", "snooze"}, "none", Snap::Response::None }
+ };
+
+
+ settings->cal_notification_enabled.set(true);
+ settings->cal_notification_sounds.set(true);
+ settings->cal_notification_vibrations.set(true);
+ settings->cal_notification_bubbles.set(true);
+ settings->cal_notification_list.set(true);
+
+ // walk through the tests
+ for (const auto& test : tests)
+ {
+ // wait for previous iterations' bus noise to finish and reset the counters
+ GError* error {};
+ wait_msec(500);
+ dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error);
+ g_assert_no_error(error);
+ on_response_called = false;
+
+ // create a snap decision
+ auto snap = create_snap(ne, sb, settings);
+ (*snap)(test.appt, test.appt.alarms.front(), on_response);
+
+ // wait for the notification to show up
+ EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY);
+
+ // test that Notify was called the right number of times
+ static constexpr int expected_num_notify_calls {1};
+ guint num_notify_calls {};
+ const auto notify_calls = dbus_test_dbus_mock_object_get_method_calls(
+ notify_mock,
+ notify_obj,
+ METHOD_NOTIFY,
+ &num_notify_calls,
+ &error);
+ g_assert_no_error(error);
+ EXPECT_EQ(expected_num_notify_calls, num_notify_calls);
+
+ // test that Notify was called with the correct list of actions
+ if (num_notify_calls > 0) {
+ std::vector<std::string> actions;
+ const gchar** as {nullptr};
+ g_variant_get_child(notify_calls[0].params, 5, "^a&s", &as);
+ for (int i=0; as && as[i]; i+=2) // actions are in pairs of (name, i18n), skip the i18n
+ actions.push_back(as[i]);
+ EXPECT_EQ(test.expected_actions, actions);
+ }
+
+ // make the notification mock tell the world that the user invoked an action
+ const auto notification_id = next_notification_id++;
+ idle_add([this, notification_id, test](){
+ GError* err {};
+ dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "ActionInvoked",
+ G_VARIANT_TYPE("(us)"),
+ g_variant_new("(us)", guint(notification_id), test.action.c_str()),
+ &err);
+ dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "NotificationClosed",
+ G_VARIANT_TYPE("(uu)"),
+ g_variant_new("(uu)", guint(notification_id), guint(NOTIFICATION_CLOSED_DISMISSED)),
+ &err);
+ g_assert_no_error(err);
+ return G_SOURCE_REMOVE;
+ });
+
+ // confirm that the response callback got the right response
+ EXPECT_TRUE(wait_for([&on_response_called](){return on_response_called;}));
+ EXPECT_EQ(int(test.expected_response), int(response)) << "notification_id " << notification_id;
+ }
+}
diff --git a/tests/test-notification.cpp b/tests/test-notification.cpp
index 0db6ab9..83a021f 100644
--- a/tests/test-notification.cpp
+++ b/tests/test-notification.cpp
@@ -196,103 +196,3 @@ TEST_F(NotificationFixture,Notification)
}
}
}
-
-
-TEST_F(NotificationFixture,Response)
-{
- // create the world
- make_interactive();
- auto ne = std::make_shared<ayatana::indicator::notifications::Engine>(APP_NAME);
- auto sb = std::make_shared<ayatana::indicator::notifications::DefaultSoundBuilder>();
- auto settings = std::make_shared<Settings>();
- int next_notification_id {FIRST_NOTIFY_ID};
-
- // set a response callback that remembers what response we got
- bool on_response_called {};
- Snap::Response response {};
- auto on_response = [this, &on_response_called, &response]
- (const Appointment&, const Alarm&, const Snap::Response& r){
- on_response_called = true;
- response = r;
- g_idle_add(quit_idle, loop);
- };
-
- // our tests!
- const struct {
- Appointment appt;
- std::vector<std::string> expected_actions;
- std::string action;
- Snap::Response expected_response;
- } tests[] = {
- { appt, {"show-app"}, "show-app", Snap::Response::ShowApp },
- { ualarm, {"none", "snooze"}, "snooze", Snap::Response::Snooze },
- { ualarm, {"none", "snooze"}, "none", Snap::Response::None }
- };
-
-
- settings->cal_notification_enabled.set(true);
- settings->cal_notification_sounds.set(true);
- settings->cal_notification_vibrations.set(true);
- settings->cal_notification_bubbles.set(true);
- settings->cal_notification_list.set(true);
-
- // walk through the tests
- for (const auto& test : tests)
- {
- // wait for previous iterations' bus noise to finish and reset the counters
- GError* error {};
- wait_msec(500);
- dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error);
- g_assert_no_error(error);
- on_response_called = false;
-
- // create a snap decision
- auto snap = create_snap(ne, sb, settings);
- (*snap)(test.appt, test.appt.alarms.front(), on_response);
-
- // wait for the notification to show up
- EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY);
-
- // test that Notify was called the right number of times
- static constexpr int expected_num_notify_calls {1};
- guint num_notify_calls {};
- const auto notify_calls = dbus_test_dbus_mock_object_get_method_calls(
- notify_mock,
- notify_obj,
- METHOD_NOTIFY,
- &num_notify_calls,
- &error);
- g_assert_no_error(error);
- EXPECT_EQ(expected_num_notify_calls, num_notify_calls);
-
- // test that Notify was called with the correct list of actions
- if (num_notify_calls > 0) {
- std::vector<std::string> actions;
- const gchar** as {nullptr};
- g_variant_get_child(notify_calls[0].params, 5, "^a&s", &as);
- for (int i=0; as && as[i]; i+=2) // actions are in pairs of (name, i18n), skip the i18n
- actions.push_back(as[i]);
- EXPECT_EQ(test.expected_actions, actions);
- }
-
- // make the notification mock tell the world that the user invoked an action
- const auto notification_id = next_notification_id++;
- idle_add([this, notification_id, test](){
- GError* err {};
- dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "ActionInvoked",
- G_VARIANT_TYPE("(us)"),
- g_variant_new("(us)", guint(notification_id), test.action.c_str()),
- &err);
- dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "NotificationClosed",
- G_VARIANT_TYPE("(uu)"),
- g_variant_new("(uu)", guint(notification_id), guint(NOTIFICATION_CLOSED_DISMISSED)),
- &err);
- g_assert_no_error(err);
- return G_SOURCE_REMOVE;
- });
-
- // confirm that the response callback got the right response
- EXPECT_TRUE(wait_for([&on_response_called](){return on_response_called;}));
- EXPECT_EQ(int(test.expected_response), int(response)) << "notification_id " << notification_id;
- }
-}