From 62f4861b11ba7e3c58c75cf574cc999e623b4247 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 10 Feb 2016 14:49:01 -0600 Subject: update notification tests to wait for the needed bus events instead of waiting for arbitrary time intervals --- tests/test-notification.cpp | 65 ++++++-- tests/test-snap.cpp | 396 -------------------------------------------- tests/test-sound.cpp | 100 ----------- 3 files changed, 48 insertions(+), 513 deletions(-) delete mode 100644 tests/test-snap.cpp diff --git a/tests/test-notification.cpp b/tests/test-notification.cpp index 5a2682e..a51267f 100644 --- a/tests/test-notification.cpp +++ b/tests/test-notification.cpp @@ -37,7 +37,18 @@ namespace { g_main_loop_quit(static_cast(gloop)); return G_SOURCE_REMOVE; - }; + } + + void on_dbus_signal(GDBusConnection* /*connection*/, + const gchar* /*sender_name*/, + const gchar* /*object_path*/, + const gchar* /*interface_name*/, + const gchar* /*signal_name*/, + GVariant* /*parameters*/, + gpointer gloop) + { + g_main_loop_quit(static_cast(gloop)); + } } /*** @@ -122,28 +133,58 @@ TEST_F(NotificationFixture,Notification) && test_haptic.expected_vibrate_called; // clear out any previous iterations' noise - GError * error = nullptr; + GError * error {}; dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error); - g_assert_no_error(error); dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error); g_assert_no_error(error); - // set the properties to match the test case + + // set test case properties: blacklist settings->muted_apps.set(test_muted.muted_apps); + + // set test case properties: haptic mode settings->alarm_haptic.set(test_haptic.haptic_mode); + + // set test case properties: other-vibrations flag + // (and wait for the PropertiesChanged signal so we know the dbusmock got it) + ASSERT_NAME_OWNED_EVENTUALLY(system_bus, AS_BUSNAME); + const auto subscription_id = g_dbus_connection_signal_subscribe(system_bus, + AS_BUSNAME, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + nullptr, /* object_path */ + "com.lomiri.touch.AccountsService.Sound", + G_DBUS_SIGNAL_FLAGS_NONE, + on_dbus_signal, + loop, + nullptr /*user_data_free_func*/); dbus_test_dbus_mock_object_update_property(as_mock, as_obj, PROP_OTHER_VIBRATIONS, g_variant_new_boolean(test_vibes.other_vibrations), &error); g_assert_no_error(error); - wait_msec(100); + g_main_loop_run(loop); + g_dbus_connection_signal_unsubscribe(system_bus, subscription_id); // run the test (*snap)(test_appt.appt, appt.alarms.front(), func, func); - wait_msec(100); - // test that the notification was as expected + // confirm that the notification was as expected + if (expected_notify_called) { + EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY); + } else { + EXPECT_METHOD_NOT_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY); + } + + // confirm that the vibration was as expected + if (expected_vibrate_called) { + EXPECT_METHOD_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE_PATTERN); + } else { + EXPECT_METHOD_NOT_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE_PATTERN); + } + + // confirm that the notification was as expected guint num_notify_calls = 0; const auto notify_calls = dbus_test_dbus_mock_object_get_method_calls(notify_mock, notify_obj, @@ -151,7 +192,6 @@ TEST_F(NotificationFixture,Notification) &num_notify_calls, &error); g_assert_no_error(error); - EXPECT_EQ((expected_notify_called?1:0), num_notify_calls); if (num_notify_calls > 0) { // test that Notify was called with the app_name @@ -174,15 +214,6 @@ TEST_F(NotificationFixture,Notification) g_variant_get_child(notify_calls[0].params, 4, "&s", &body); ASSERT_STREQ(test_appt.appt.summary.c_str(), body); } - - // test that the vibration was as expected - const bool vibrate_called = dbus_test_dbus_mock_object_check_method_call(haptic_mock, - haptic_obj, - HAPTIC_METHOD_VIBRATE_PATTERN, - nullptr, - &error); - g_assert_no_error(error); - EXPECT_EQ(expected_vibrate_called, vibrate_called); } } } diff --git a/tests/test-snap.cpp b/tests/test-snap.cpp deleted file mode 100644 index 2c53900..0000000 --- a/tests/test-snap.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2014 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include -#include -#include -#include - -#include -#include - -#include "notification-fixture.h" - -using namespace ayatana::indicator::datetime; - -namespace uin = ayatana::indicator::notifications; - -/*** -**** -***/ - -namespace -{ - static constexpr char const * APP_NAME {"ayatana-indicator-datetime-service"}; -} - -using namespace ayatana::indicator::datetime; - -/*** -**** -***/ - -namespace -{ - gboolean quit_idle (gpointer gloop) - { - g_main_loop_quit(static_cast(gloop)); - return G_SOURCE_REMOVE; - }; -} - -TEST_F(NotificationFixture, InteractiveDuration) -{ - static constexpr int duration_minutes = 120; - auto settings = std::make_shared(); - settings->alarm_duration.set(duration_minutes); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto snap = create_snap(ne, sb, settings); - - make_interactive(); - - // call the Snap Decision - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - (*snap)(appt, appt.alarms.front(), func, func); - - // confirm that Notify got called once - guint len = 0; - GError * error = nullptr; - const auto calls = dbus_test_dbus_mock_object_get_method_calls (notify_mock, - notify_obj, - METHOD_NOTIFY, - &len, - &error); - g_assert_no_error(error); - ASSERT_EQ(1, len); - - // confirm that the app_name passed to Notify was APP_NAME - const auto& params = calls[0].params; - ASSERT_EQ(8, g_variant_n_children(params)); - const char * str = nullptr; - g_variant_get_child (params, 0, "&s", &str); - ASSERT_STREQ(APP_NAME, str); - - // confirm that the icon passed to Notify was "alarm-clock" - g_variant_get_child (params, 2, "&s", &str); - ASSERT_STREQ("alarm-clock", str); - - // confirm that the hints passed to Notify included a timeout matching duration_minutes - int32_t i32; - bool b; - auto hints = g_variant_get_child_value (params, 6); - b = g_variant_lookup (hints, HINT_TIMEOUT, "i", &i32); - EXPECT_TRUE(b); - const auto duration = std::chrono::minutes(duration_minutes); - EXPECT_EQ(std::chrono::duration_cast(duration).count(), i32); - g_variant_unref(hints); - ne.reset(); -} - -/*** -**** -***/ - -TEST_F(NotificationFixture, InhibitSleep) -{ - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto snap = create_snap(ne, sb, settings); - - make_interactive(); - - // invoke the notification - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - (*snap)(appt, appt.alarms.front(), func, func); - - wait_msec(1000); - - // confirm that sleep got inhibited - GError * error = nullptr; - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_REQUEST_SYS_STATE, - g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE), - &error)); - - // confirm that the screen got forced on - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock, - screen_obj, - SCREEN_METHOD_KEEP_DISPLAY_ON, - nullptr, - &error)); - - // force-close the snap - wait_msec(100); - snap.reset(); - wait_msec(100); - - // confirm that sleep got uninhibted - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_CLEAR_SYS_STATE, - g_variant_new("(s)", POWERD_COOKIE), - &error)); - - // confirm that the screen's no longer forced on - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock, - screen_obj, - SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST, - g_variant_new("(i)", SCREEN_COOKIE), - &error)); - - g_assert_no_error (error); -} - -/*** -**** -***/ - -TEST_F(NotificationFixture, ForceScreen) -{ - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto snap = create_snap(ne, sb, settings); - - make_interactive(); - - // invoke the notification - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - (*snap)(appt, appt.alarms.front(), func, func); - - wait_msec(1000); - - // confirm that sleep got inhibited - GError * error = nullptr; - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_REQUEST_SYS_STATE, - g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE), - &error)); - g_assert_no_error(error); - - // force-close the snap - wait_msec(100); - snap.reset(); - wait_msec(100); - - // confirm that sleep got uninhibted - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_CLEAR_SYS_STATE, - g_variant_new("(s)", POWERD_COOKIE), - &error)); - g_assert_no_error(error); -} - -/*** -**** -***/ - -/** - * A DefaultSoundBuilder wrapper which remembers the parameters of the last sound created. - */ -class TestSoundBuilder: public uin::SoundBuilder -{ -public: - TestSoundBuilder() =default; - ~TestSoundBuilder() =default; - - virtual std::shared_ptr create(const std::string& role, const std::string& uri, unsigned int volume, bool loop) override { - m_role = role; - m_uri = uri; - m_volume = volume; - m_loop = loop; - return m_impl.create(role, uri, volume, loop); - } - - const std::string& role() { return m_role; } - const std::string& uri() { return m_uri; } - unsigned int volume() { return m_volume; } - bool loop() { return m_loop; } - -private: - std::string m_role; - std::string m_uri; - unsigned int m_volume; - bool m_loop; - uin::DefaultSoundBuilder m_impl; -}; - -std::string path_to_uri(const std::string& path) -{ - auto file = g_file_new_for_path(path.c_str()); - auto uri_cstr = g_file_get_uri(file); - std::string uri = uri_cstr; - g_free(uri_cstr); - g_clear_pointer(&file, g_object_unref); - return uri; -} - -TEST_F(NotificationFixture,DefaultSounds) -{ - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - - const struct { - Appointment appointment; - std::string expected_role; - std::string expected_uri; - } test_cases[] = { - { ualarm, "alarm", path_to_uri(ALARM_DEFAULT_SOUND) }, - { appt, "alert", path_to_uri(CALENDAR_DEFAULT_SOUND) } - }; - - auto snap = create_snap(ne, sb, settings); - - for(const auto& test_case : test_cases) - { - (*snap)(test_case.appointment, test_case.appointment.alarms.front(), func, func); - wait_msec(100); - EXPECT_EQ(test_case.expected_uri, sb->uri()); - EXPECT_EQ(test_case.expected_role, sb->role()); - } -} - -/*** -**** -***/ - -TEST_F(NotificationFixture,Notification) -{ - // Feed different combinations of system settings, - // indicator-datetime settings, and event types, - // then see if notifications and haptic feedback behave as expected. - - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - - // combinatorial factor #1: event type - struct { - Appointment appt; - bool expected_notify_called; - bool expected_vibrate_called; - } test_appts[] = { - { appt, true, true }, - { ualarm, true, true } - }; - - // combinatorial factor #2: indicator-datetime's haptic mode - struct { - const char* haptic_mode; - bool expected_notify_called; - bool expected_vibrate_called; - } test_haptics[] = { - { "none", true, false }, - { "pulse", true, true } - }; - - // combinatorial factor #3: system settings' "other vibrations" enabled - struct { - bool other_vibrations; - bool expected_notify_called; - bool expected_vibrate_called; - } test_other_vibrations[] = { - { true, true, true }, - { false, true, false } - }; - - // combinatorial factor #4: system settings' notifications app blacklist - const std::set> blacklist_calendar { std::make_pair(std::string{"com.lomiri.calendar"}, std::string{"calendar-app"}) }; - const std::set> blacklist_empty; - struct { - std::set> muted_apps; // apps that should not trigger notifications - bool expected_notify_called; // do we expect the notification tho show? - bool expected_vibrate_called; // do we expect the phone to vibrate? - } test_muted_apps[] = { - { blacklist_calendar, false, false }, - { blacklist_empty, true, true } - }; - - for (const auto& test_appt : test_appts) - { - for (const auto& test_haptic : test_haptics) - { - for (const auto& test_vibes : test_other_vibrations) - { - for (const auto& test_muted : test_muted_apps) - { - auto snap = create_snap(ne, sb, settings); - - const bool expected_notify_called = test_appt.expected_notify_called - && test_vibes.expected_notify_called - && test_muted.expected_notify_called - && test_haptic.expected_notify_called; - - const bool expected_vibrate_called = test_appt.expected_vibrate_called - && test_vibes.expected_vibrate_called - && test_muted.expected_vibrate_called - && test_haptic.expected_vibrate_called; - - // clear out any previous iterations' noise - GError * error = nullptr; - dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error); - g_assert_no_error(error); - dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error); - g_assert_no_error(error); - - // set the properties to match the test case - settings->muted_apps.set(test_muted.muted_apps); - settings->alarm_haptic.set(test_haptic.haptic_mode); - dbus_test_dbus_mock_object_update_property(as_mock, - as_obj, - PROP_OTHER_VIBRATIONS, - g_variant_new_boolean(test_vibes.other_vibrations), - &error); - g_assert_no_error(error); - wait_msec(100); - - // run the test - (*snap)(appt, appt.alarms.front(), func, func); - wait_msec(100); - - // test that the notification was as expected - const bool notify_called = dbus_test_dbus_mock_object_check_method_call(notify_mock, - notify_obj, - METHOD_NOTIFY, - nullptr, - &error); - g_assert_no_error(error); - EXPECT_EQ(expected_notify_called, notify_called); - - // test that the vibration was as expected - const bool vibrate_called = dbus_test_dbus_mock_object_check_method_call(haptic_mock, - haptic_obj, - HAPTIC_METHOD_VIBRATE_PATTERN, - nullptr, - &error); - g_assert_no_error(error); - EXPECT_EQ(expected_vibrate_called, vibrate_called); - } - } - } - } -} diff --git a/tests/test-sound.cpp b/tests/test-sound.cpp index c2a8fb5..a222f39 100644 --- a/tests/test-sound.cpp +++ b/tests/test-sound.cpp @@ -103,104 +103,6 @@ TEST_F(NotificationFixture, InteractiveDuration) **** ***/ -TEST_F(NotificationFixture, InhibitSleep) -{ - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto snap = create_snap(ne, sb, settings); - - make_interactive(); - - // invoke the notification - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - (*snap)(appt, appt.alarms.front(), func, func); - - wait_msec(1000); - - // confirm that sleep got inhibited - GError * error = nullptr; - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_REQUEST_SYS_STATE, - g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE), - &error)); - - // confirm that the screen got forced on - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock, - screen_obj, - SCREEN_METHOD_KEEP_DISPLAY_ON, - nullptr, - &error)); - - // force-close the snap - wait_msec(100); - snap.reset(); - wait_msec(100); - - // confirm that sleep got uninhibted - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_CLEAR_SYS_STATE, - g_variant_new("(s)", POWERD_COOKIE), - &error)); - - // confirm that the screen's no longer forced on - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (screen_mock, - screen_obj, - SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST, - g_variant_new("(i)", SCREEN_COOKIE), - &error)); - - g_assert_no_error (error); -} - -/*** -**** -***/ - -TEST_F(NotificationFixture, ForceScreen) -{ - auto settings = std::make_shared(); - auto ne = std::make_shared(APP_NAME); - auto sb = std::make_shared(); - auto snap = create_snap(ne, sb, settings); - - make_interactive(); - - // invoke the notification - auto func = [this](const Appointment&, const Alarm&){g_idle_add(quit_idle, loop);}; - (*snap)(appt, appt.alarms.front(), func, func); - - wait_msec(1000); - - // confirm that sleep got inhibited - GError * error = nullptr; - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_REQUEST_SYS_STATE, - g_variant_new("(si)", APP_NAME, POWERD_SYS_STATE_ACTIVE), - &error)); - g_assert_no_error(error); - - // force-close the snap - wait_msec(100); - snap.reset(); - wait_msec(100); - - // confirm that sleep got uninhibted - EXPECT_TRUE (dbus_test_dbus_mock_object_check_method_call (powerd_mock, - powerd_obj, - POWERD_METHOD_CLEAR_SYS_STATE, - g_variant_new("(s)", POWERD_COOKIE), - &error)); - g_assert_no_error(error); -} - -/*** -**** -***/ - /** * A DefaultSoundBuilder wrapper which remembers the parameters of the last sound created. */ @@ -258,11 +160,9 @@ TEST_F(NotificationFixture,DefaultSounds) }; auto snap = create_snap(ne, sb, settings); - for(const auto& test_case : test_cases) { (*snap)(test_case.appointment, test_case.appointment.alarms.front(), func, func); - wait_msec(100); EXPECT_EQ(test_case.expected_uri, sb->uri()); EXPECT_EQ(test_case.expected_role, sb->role()); } -- cgit v1.2.3