~ci-train-bot/indicator-sound/indicator-sound-ubuntu-zesty-2138

« back to all changes in this revision

Viewing changes to tests/notifications-test.cc

  • Committer: CI Train Bot
  • Author(s): Xavi Garcia Mena
  • Date: 2016-03-07 10:13:38 UTC
  • mfrom: (529.1.8 last-runnin-player-charles)
  • Revision ID: ci-train-bot@canonical.com-20160307101338-x2wynmsb4sch7jag
This branch sets the last running player using accounts service instead of gsettings.
It also includes a new class AccountsServiceAccess, to centralize all accesses to account service properties.
Approved by: PS Jenkins bot, Charles Kerr

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
class NotificationsTest : public ::testing::Test
38
38
{
39
 
        protected:
40
 
                DbusTestService * service = NULL;
41
 
 
42
 
                GDBusConnection * session = NULL;
43
 
                std::shared_ptr<NotificationsMock> notifications;
44
 
 
45
 
                virtual void SetUp() {
46
 
                        g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
47
 
                        g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
48
 
 
49
 
                        service = dbus_test_service_new(NULL);
50
 
                        dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SESSION);
51
 
 
52
 
                        /* Useful for debugging test failures, not needed all the time (until it fails) */
53
 
                        #if 0
54
 
                        auto bustle = std::shared_ptr<DbusTestTask>([]() {
55
 
                                DbusTestTask * bustle = DBUS_TEST_TASK(dbus_test_bustle_new("notifications-test.bustle"));
56
 
                                dbus_test_task_set_name(bustle, "Bustle");
57
 
                                dbus_test_task_set_bus(bustle, DBUS_TEST_SERVICE_BUS_SESSION);
58
 
                                return bustle;
59
 
                        }(), [](DbusTestTask * bustle) {
60
 
                                g_clear_object(&bustle);
61
 
                        });
62
 
                        dbus_test_service_add_task(service, bustle.get());
63
 
                        #endif
64
 
 
65
 
                        notifications = std::make_shared<NotificationsMock>();
66
 
 
67
 
                        dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
68
 
                        dbus_test_service_start_tasks(service);
69
 
 
70
 
                        session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
71
 
                        ASSERT_NE(nullptr, session);
72
 
                        g_dbus_connection_set_exit_on_close(session, FALSE);
73
 
                        g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
74
 
 
75
 
                        /* This is done in main.c */
76
 
                        notify_init("indicator-sound");
77
 
                }
78
 
 
79
 
                virtual void TearDown() {
80
 
                        if (notify_is_initted())
81
 
                                notify_uninit();
82
 
 
83
 
                        notifications.reset();
84
 
                        g_clear_object(&service);
85
 
 
86
 
                        g_object_unref(session);
87
 
 
88
 
                        unsigned int cleartry = 0;
89
 
                        while (session != NULL && cleartry < 100) {
90
 
                                loop(100);
91
 
                                cleartry++;
92
 
                        }
93
 
 
94
 
                        ASSERT_EQ(nullptr, session);
95
 
                }
96
 
 
97
 
                static gboolean timeout_cb (gpointer user_data) {
98
 
                        GMainLoop * loop = static_cast<GMainLoop *>(user_data);
99
 
                        g_main_loop_quit(loop);
100
 
                        return G_SOURCE_REMOVE;
101
 
                }
102
 
 
103
 
                void loop (unsigned int ms) {
104
 
                        GMainLoop * loop = g_main_loop_new(NULL, FALSE);
105
 
                        g_timeout_add(ms, timeout_cb, loop);
106
 
                        g_main_loop_run(loop);
107
 
                        g_main_loop_unref(loop);
108
 
                }
109
 
 
110
 
                void loop_until(const std::function<bool()>& test, unsigned int max_ms=50, unsigned int test_interval_ms=10) {
111
 
 
112
 
                        // g_timeout's callback only allows a single pointer,
113
 
                        // so use a temporary stack struct to wedge everything into one pointer
114
 
                        struct CallbackData {
115
 
                                const std::function<bool()>& test;
116
 
                                const gint64 deadline;
117
 
                                GMainLoop* loop = g_main_loop_new(nullptr, false);
118
 
                                CallbackData (const std::function<bool()>& f, unsigned int max_ms):
119
 
                                        test{f},
120
 
                                        deadline{g_get_monotonic_time() + (max_ms*1000)} {}
121
 
                                ~CallbackData() {g_main_loop_unref(loop);}
122
 
                        } data(test, max_ms);
123
 
 
124
 
                        // tell the timer to stop looping on success or deadline
125
 
                        auto timerfunc = [](gpointer gdata) -> gboolean {
126
 
                                auto& data = *static_cast<CallbackData*>(gdata);
127
 
                                if (!data.test() && (g_get_monotonic_time() < data.deadline))
128
 
                                        return G_SOURCE_CONTINUE;
129
 
                                g_main_loop_quit(data.loop);
130
 
                                return G_SOURCE_REMOVE;
131
 
                        };
132
 
 
133
 
                        // start looping
134
 
                        g_timeout_add (std::min(max_ms, test_interval_ms), timerfunc, &data);
135
 
                        g_main_loop_run(data.loop);
136
 
                }
137
 
 
138
 
                void loop_until_notifications(unsigned int max_seconds=1) {
139
 
                        auto test = [this]{ return !notifications->getNotifications().empty(); };
140
 
                        loop_until(test, max_seconds);
141
 
                }
142
 
 
143
 
                static int unref_idle (gpointer user_data) {
144
 
                        g_variant_unref(static_cast<GVariant *>(user_data));
145
 
                        return G_SOURCE_REMOVE;
146
 
                }
147
 
 
148
 
                std::shared_ptr<MediaPlayerList> playerListMock () {
149
 
                        auto playerList = std::shared_ptr<MediaPlayerList>(
150
 
                                MEDIA_PLAYER_LIST(media_player_list_mock_new()),
151
 
                                [](MediaPlayerList * list) {
152
 
                                        g_clear_object(&list);
153
 
                                });
154
 
                        return playerList;
155
 
                }
156
 
 
157
 
                std::shared_ptr<IndicatorSoundOptions> optionsMock () {
158
 
                        auto options = std::shared_ptr<IndicatorSoundOptions>(
159
 
                                INDICATOR_SOUND_OPTIONS(options_mock_new()),
160
 
                                [](IndicatorSoundOptions * options){
161
 
                                        g_clear_object(&options);
162
 
                                });
163
 
                        return options;
164
 
                }
165
 
 
166
 
                std::shared_ptr<VolumeControl> volumeControlMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) {
167
 
                        auto volumeControl = std::shared_ptr<VolumeControl>(
168
 
                                VOLUME_CONTROL(volume_control_mock_new(optionsMock.get())),
169
 
                                [](VolumeControl * control){
170
 
                                        g_clear_object(&control);
171
 
                                });
172
 
                        return volumeControl;
173
 
                }
174
 
 
175
 
                std::shared_ptr<VolumeWarning> volumeWarningMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) {
176
 
                        auto volumeWarning = std::shared_ptr<VolumeWarning>(
177
 
                                VOLUME_WARNING(volume_warning_mock_new(optionsMock.get())),
178
 
                                [](VolumeWarning * warning){
179
 
                                        g_clear_object(&warning);
180
 
                                });
181
 
                        return volumeWarning;
182
 
                }
183
 
 
184
 
                std::shared_ptr<IndicatorSoundService> standardService (
185
 
                                const std::shared_ptr<VolumeControl>& volumeControl,
186
 
                                const std::shared_ptr<MediaPlayerList>& playerList,
187
 
                                const std::shared_ptr<IndicatorSoundOptions>& options,
188
 
                                const std::shared_ptr<VolumeWarning>& warning) {
189
 
                        auto soundService = std::shared_ptr<IndicatorSoundService>(
190
 
                                indicator_sound_service_new(playerList.get(), volumeControl.get(), nullptr, options.get(), warning.get()),
191
 
                                [](IndicatorSoundService * service){
192
 
                                        g_clear_object(&service);
193
 
                                });
194
 
 
195
 
                        return soundService;
196
 
                }
197
 
 
198
 
                void setMockVolume (std::shared_ptr<VolumeControl> volumeControl, double volume, VolumeControlVolumeReasons reason = VOLUME_CONTROL_VOLUME_REASONS_USER_KEYPRESS) {
199
 
                        VolumeControlVolume * vol = volume_control_volume_new();
200
 
                        vol->volume = volume;
201
 
                        vol->reason = reason;
202
 
 
203
 
                        volume_control_set_volume(volumeControl.get(), vol);
204
 
                        g_object_unref(vol);
205
 
                }
206
 
 
207
 
                void setIndicatorShown (bool shown) {
208
 
                        auto bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
209
 
 
210
 
                        g_dbus_connection_call(bus,
211
 
                                g_dbus_connection_get_unique_name(bus),
212
 
                                "/com/canonical/indicator/sound",
213
 
                                "org.gtk.Actions",
214
 
                                "SetState",
215
 
                                g_variant_new("(sva{sv})", "indicator-shown", g_variant_new_boolean(shown), nullptr),
216
 
                                nullptr,
217
 
                                G_DBUS_CALL_FLAGS_NONE,
218
 
                                -1,
219
 
                                nullptr,
220
 
                                nullptr,
221
 
                                nullptr);
222
 
 
223
 
                        g_clear_object(&bus);
224
 
                }
 
39
    protected:
 
40
        DbusTestService * service = NULL;
 
41
 
 
42
        GDBusConnection * session = NULL;
 
43
        std::shared_ptr<NotificationsMock> notifications;
 
44
 
 
45
        virtual void SetUp() {
 
46
            g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
 
47
            g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
 
48
 
 
49
            service = dbus_test_service_new(NULL);
 
50
            dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SESSION);
 
51
 
 
52
            /* Useful for debugging test failures, not needed all the time (until it fails) */
 
53
            #if 0
 
54
            auto bustle = std::shared_ptr<DbusTestTask>([]() {
 
55
                DbusTestTask * bustle = DBUS_TEST_TASK(dbus_test_bustle_new("notifications-test.bustle"));
 
56
                dbus_test_task_set_name(bustle, "Bustle");
 
57
                dbus_test_task_set_bus(bustle, DBUS_TEST_SERVICE_BUS_SESSION);
 
58
                return bustle;
 
59
            }(), [](DbusTestTask * bustle) {
 
60
                g_clear_object(&bustle);
 
61
            });
 
62
            dbus_test_service_add_task(service, bustle.get());
 
63
            #endif
 
64
 
 
65
            notifications = std::make_shared<NotificationsMock>();
 
66
 
 
67
            dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
 
68
            dbus_test_service_start_tasks(service);
 
69
 
 
70
            session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
 
71
            ASSERT_NE(nullptr, session);
 
72
            g_dbus_connection_set_exit_on_close(session, FALSE);
 
73
            g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
 
74
 
 
75
            /* This is done in main.c */
 
76
            notify_init("indicator-sound");
 
77
        }
 
78
 
 
79
        virtual void TearDown() {
 
80
            if (notify_is_initted())
 
81
                notify_uninit();
 
82
 
 
83
            notifications.reset();
 
84
            g_clear_object(&service);
 
85
 
 
86
            g_object_unref(session);
 
87
 
 
88
            unsigned int cleartry = 0;
 
89
            while (session != NULL && cleartry < 100) {
 
90
                loop(100);
 
91
                cleartry++;
 
92
            }
 
93
 
 
94
            ASSERT_EQ(nullptr, session);
 
95
        }
 
96
 
 
97
        static gboolean timeout_cb (gpointer user_data) {
 
98
            GMainLoop * loop = static_cast<GMainLoop *>(user_data);
 
99
            g_main_loop_quit(loop);
 
100
            return G_SOURCE_REMOVE;
 
101
        }
 
102
 
 
103
        void loop (unsigned int ms) {
 
104
            GMainLoop * loop = g_main_loop_new(NULL, FALSE);
 
105
            g_timeout_add(ms, timeout_cb, loop);
 
106
            g_main_loop_run(loop);
 
107
            g_main_loop_unref(loop);
 
108
        }
 
109
 
 
110
        void loop_until(const std::function<bool()>& test, unsigned int max_ms=50, unsigned int test_interval_ms=10) {
 
111
 
 
112
            // g_timeout's callback only allows a single pointer,
 
113
            // so use a temporary stack struct to wedge everything into one pointer
 
114
            struct CallbackData {
 
115
                const std::function<bool()>& test;
 
116
                const gint64 deadline;
 
117
                GMainLoop* loop = g_main_loop_new(nullptr, false);
 
118
                CallbackData (const std::function<bool()>& f, unsigned int max_ms):
 
119
                    test{f},
 
120
                    deadline{g_get_monotonic_time() + (max_ms*1000)} {}
 
121
                ~CallbackData() {g_main_loop_unref(loop);}
 
122
            } data(test, max_ms);
 
123
 
 
124
            // tell the timer to stop looping on success or deadline
 
125
            auto timerfunc = [](gpointer gdata) -> gboolean {
 
126
                auto& data = *static_cast<CallbackData*>(gdata);
 
127
                if (!data.test() && (g_get_monotonic_time() < data.deadline))
 
128
                    return G_SOURCE_CONTINUE;
 
129
                g_main_loop_quit(data.loop);
 
130
                return G_SOURCE_REMOVE;
 
131
            };
 
132
 
 
133
            // start looping
 
134
            g_timeout_add (std::min(max_ms, test_interval_ms), timerfunc, &data);
 
135
            g_main_loop_run(data.loop);
 
136
        }
 
137
 
 
138
        void loop_until_notifications(unsigned int max_seconds=1) {
 
139
            auto test = [this]{ return !notifications->getNotifications().empty(); };
 
140
            loop_until(test, max_seconds);
 
141
        }
 
142
 
 
143
        static int unref_idle (gpointer user_data) {
 
144
            g_variant_unref(static_cast<GVariant *>(user_data));
 
145
            return G_SOURCE_REMOVE;
 
146
        }
 
147
 
 
148
        std::shared_ptr<MediaPlayerList> playerListMock () {
 
149
            auto playerList = std::shared_ptr<MediaPlayerList>(
 
150
                MEDIA_PLAYER_LIST(media_player_list_mock_new()),
 
151
                [](MediaPlayerList * list) {
 
152
                    g_clear_object(&list);
 
153
                });
 
154
            return playerList;
 
155
        }
 
156
 
 
157
        std::shared_ptr<IndicatorSoundOptions> optionsMock () {
 
158
            auto options = std::shared_ptr<IndicatorSoundOptions>(
 
159
                INDICATOR_SOUND_OPTIONS(options_mock_new()),
 
160
                [](IndicatorSoundOptions * options){
 
161
                    g_clear_object(&options);
 
162
                });
 
163
            return options;
 
164
        }
 
165
 
 
166
        std::shared_ptr<VolumeControl> volumeControlMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) {
 
167
            auto volumeControl = std::shared_ptr<VolumeControl>(
 
168
                VOLUME_CONTROL(volume_control_mock_new(optionsMock.get())),
 
169
                [](VolumeControl * control){
 
170
                    g_clear_object(&control);
 
171
                });
 
172
            return volumeControl;
 
173
        }
 
174
 
 
175
        std::shared_ptr<VolumeWarning> volumeWarningMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) {
 
176
            auto volumeWarning = std::shared_ptr<VolumeWarning>(
 
177
                VOLUME_WARNING(volume_warning_mock_new(optionsMock.get())),
 
178
                [](VolumeWarning * warning){
 
179
                    g_clear_object(&warning);
 
180
                });
 
181
            return volumeWarning;
 
182
        }
 
183
 
 
184
        std::shared_ptr<IndicatorSoundService> standardService (
 
185
                const std::shared_ptr<VolumeControl>& volumeControl,
 
186
                const std::shared_ptr<MediaPlayerList>& playerList,
 
187
                const std::shared_ptr<IndicatorSoundOptions>& options,
 
188
                const std::shared_ptr<VolumeWarning>& warning,
 
189
                const std::shared_ptr<AccountsServiceAccess>& accounts_service_access) {
 
190
            auto soundService = std::shared_ptr<IndicatorSoundService>(
 
191
                indicator_sound_service_new(playerList.get(), volumeControl.get(), nullptr, options.get(), warning.get(), accounts_service_access.get()),
 
192
                [](IndicatorSoundService * service){
 
193
                    g_clear_object(&service);
 
194
                });
 
195
 
 
196
            return soundService;
 
197
        }
 
198
 
 
199
        void setMockVolume (std::shared_ptr<VolumeControl> volumeControl, double volume, VolumeControlVolumeReasons reason = VOLUME_CONTROL_VOLUME_REASONS_USER_KEYPRESS) {
 
200
            VolumeControlVolume * vol = volume_control_volume_new();
 
201
            vol->volume = volume;
 
202
            vol->reason = reason;
 
203
 
 
204
            volume_control_set_volume(volumeControl.get(), vol);
 
205
            g_object_unref(vol);
 
206
        }
 
207
 
 
208
        void setIndicatorShown (bool shown) {
 
209
            auto bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
 
210
 
 
211
            g_dbus_connection_call(bus,
 
212
                g_dbus_connection_get_unique_name(bus),
 
213
                "/com/canonical/indicator/sound",
 
214
                "org.gtk.Actions",
 
215
                "SetState",
 
216
                g_variant_new("(sva{sv})", "indicator-shown", g_variant_new_boolean(shown), nullptr),
 
217
                nullptr,
 
218
                G_DBUS_CALL_FLAGS_NONE,
 
219
                -1,
 
220
                nullptr,
 
221
                nullptr,
 
222
                nullptr);
 
223
 
 
224
            g_clear_object(&bus);
 
225
        }
225
226
 
226
227
};
227
228
 
228
229
TEST_F(NotificationsTest, BasicObject) {
229
 
        auto options = optionsMock();
230
 
        auto volumeControl = volumeControlMock(options);
231
 
        auto volumeWarning = volumeWarningMock(options);
232
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
233
 
 
234
 
        /* Give some time settle */
235
 
        loop(50);
236
 
 
237
 
        /* Auto free */
 
230
    auto options = optionsMock();
 
231
    auto volumeControl = volumeControlMock(options);
 
232
    auto volumeWarning = volumeWarningMock(options);
 
233
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
234
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
235
 
 
236
    /* Give some time settle */
 
237
    loop(50);
 
238
 
 
239
    /* Auto free */
238
240
}
239
241
 
240
242
TEST_F(NotificationsTest, VolumeChanges) {
241
 
        auto options = optionsMock();
242
 
        auto volumeControl = volumeControlMock(options);
243
 
        auto volumeWarning = volumeWarningMock(options);
244
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
245
 
 
246
 
        /* Set a volume */
247
 
        notifications->clearNotifications();
248
 
        setMockVolume(volumeControl, 0.50);
249
 
        loop(50);
250
 
        auto notev = notifications->getNotifications();
251
 
        ASSERT_EQ(1, notev.size());
252
 
        EXPECT_EQ("indicator-sound", notev[0].app_name);
253
 
        EXPECT_EQ("Volume", notev[0].summary);
254
 
        EXPECT_EQ(0, notev[0].actions.size());
255
 
        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
256
 
        EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]);
257
 
 
258
 
        /* Set a different volume */
259
 
        notifications->clearNotifications();
260
 
        setMockVolume(volumeControl, 0.60);
261
 
        loop(50);
262
 
        notev = notifications->getNotifications();
263
 
        ASSERT_EQ(1, notev.size());
264
 
        EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]);
265
 
 
266
 
        /* Have pulse set a volume */
267
 
        notifications->clearNotifications();
268
 
        setMockVolume(volumeControl, 0.70, VOLUME_CONTROL_VOLUME_REASONS_PULSE_CHANGE);
269
 
        loop(50);
270
 
        notev = notifications->getNotifications();
271
 
        ASSERT_EQ(0, notev.size());
272
 
 
273
 
        /* Have AS set the volume */
274
 
        notifications->clearNotifications();
275
 
        setMockVolume(volumeControl, 0.80, VOLUME_CONTROL_VOLUME_REASONS_ACCOUNTS_SERVICE_SET);
276
 
        loop(50);
277
 
        notev = notifications->getNotifications();
278
 
        ASSERT_EQ(0, notev.size());
 
243
    auto options = optionsMock();
 
244
    auto volumeControl = volumeControlMock(options);
 
245
    auto volumeWarning = volumeWarningMock(options);
 
246
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
247
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
248
 
 
249
    /* Set a volume */
 
250
    notifications->clearNotifications();
 
251
    setMockVolume(volumeControl, 0.50);
 
252
    loop(50);
 
253
    auto notev = notifications->getNotifications();
 
254
    ASSERT_EQ(1, notev.size());
 
255
    EXPECT_EQ("indicator-sound", notev[0].app_name);
 
256
    EXPECT_EQ("Volume", notev[0].summary);
 
257
    EXPECT_EQ(0, notev[0].actions.size());
 
258
    EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
 
259
    EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]);
 
260
 
 
261
    /* Set a different volume */
 
262
    notifications->clearNotifications();
 
263
    setMockVolume(volumeControl, 0.60);
 
264
    loop(50);
 
265
    notev = notifications->getNotifications();
 
266
    ASSERT_EQ(1, notev.size());
 
267
    EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]);
 
268
 
 
269
    /* Have pulse set a volume */
 
270
    notifications->clearNotifications();
 
271
    setMockVolume(volumeControl, 0.70, VOLUME_CONTROL_VOLUME_REASONS_PULSE_CHANGE);
 
272
    loop(50);
 
273
    notev = notifications->getNotifications();
 
274
    ASSERT_EQ(0, notev.size());
 
275
 
 
276
    /* Have AS set the volume */
 
277
    notifications->clearNotifications();
 
278
    setMockVolume(volumeControl, 0.80, VOLUME_CONTROL_VOLUME_REASONS_ACCOUNTS_SERVICE_SET);
 
279
    loop(50);
 
280
    notev = notifications->getNotifications();
 
281
    ASSERT_EQ(0, notev.size());
279
282
}
280
283
 
281
284
TEST_F(NotificationsTest, StreamChanges) {
282
 
        auto options = optionsMock();
283
 
        auto volumeControl = volumeControlMock(options);
284
 
        auto volumeWarning = volumeWarningMock(options);
285
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
286
 
 
287
 
        /* Set a volume */
288
 
        notifications->clearNotifications();
289
 
        setMockVolume(volumeControl, 0.5);
290
 
        loop(50);
291
 
        auto notev = notifications->getNotifications();
292
 
        ASSERT_EQ(1, notev.size());
293
 
 
294
 
        /* Change Streams, no volume change */
295
 
        notifications->clearNotifications();
296
 
        volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM);
297
 
        setMockVolume(volumeControl, 0.5, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
298
 
        loop(50);
299
 
        notev = notifications->getNotifications();
300
 
        EXPECT_EQ(0, notev.size());
301
 
 
302
 
        /* Change Streams, volume change */
303
 
        notifications->clearNotifications();
304
 
        volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALERT);
305
 
        setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
306
 
        loop(50);
307
 
        notev = notifications->getNotifications();
308
 
        EXPECT_EQ(0, notev.size());
309
 
 
310
 
        /* Change Streams, no volume change, volume up */
311
 
        notifications->clearNotifications();
312
 
        volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_MULTIMEDIA);
313
 
        setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
314
 
        loop(50);
315
 
        setMockVolume(volumeControl, 0.65);
316
 
        notev = notifications->getNotifications();
317
 
        EXPECT_EQ(1, notev.size());
318
 
        EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]);
 
285
    auto options = optionsMock();
 
286
    auto volumeControl = volumeControlMock(options);
 
287
    auto volumeWarning = volumeWarningMock(options);
 
288
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
289
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
290
 
 
291
    /* Set a volume */
 
292
    notifications->clearNotifications();
 
293
    setMockVolume(volumeControl, 0.5);
 
294
    loop(50);
 
295
    auto notev = notifications->getNotifications();
 
296
    ASSERT_EQ(1, notev.size());
 
297
 
 
298
    /* Change Streams, no volume change */
 
299
    notifications->clearNotifications();
 
300
    volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM);
 
301
    setMockVolume(volumeControl, 0.5, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
 
302
    loop(50);
 
303
    notev = notifications->getNotifications();
 
304
    EXPECT_EQ(0, notev.size());
 
305
 
 
306
    /* Change Streams, volume change */
 
307
    notifications->clearNotifications();
 
308
    volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALERT);
 
309
    setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
 
310
    loop(50);
 
311
    notev = notifications->getNotifications();
 
312
    EXPECT_EQ(0, notev.size());
 
313
 
 
314
    /* Change Streams, no volume change, volume up */
 
315
    notifications->clearNotifications();
 
316
    volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_MULTIMEDIA);
 
317
    setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE);
 
318
    loop(50);
 
319
    setMockVolume(volumeControl, 0.65);
 
320
    notev = notifications->getNotifications();
 
321
    EXPECT_EQ(1, notev.size());
 
322
    EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]);
319
323
}
320
324
 
321
325
TEST_F(NotificationsTest, IconTesting) {
322
 
        auto options = optionsMock();
323
 
        auto volumeControl = volumeControlMock(options);
324
 
        auto volumeWarning = volumeWarningMock(options);
325
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
326
 
 
327
 
        /* Set an initial volume */
328
 
        notifications->clearNotifications();
329
 
        setMockVolume(volumeControl, 0.5);
330
 
        loop(50);
331
 
        auto notev = notifications->getNotifications();
332
 
        ASSERT_EQ(1, notev.size());
333
 
 
334
 
        /* Generate a set of notifications */
335
 
        notifications->clearNotifications();
336
 
        for (float i = 0.0; i < 1.01; i += 0.1) {
337
 
                setMockVolume(volumeControl, i);
338
 
        }
339
 
 
340
 
        loop(50);
341
 
        notev = notifications->getNotifications();
342
 
        ASSERT_EQ(11, notev.size());
343
 
 
344
 
        EXPECT_EQ("audio-volume-muted",  notev[0].app_icon);
345
 
        EXPECT_EQ("audio-volume-low",    notev[1].app_icon);
346
 
        EXPECT_EQ("audio-volume-low",    notev[2].app_icon);
347
 
        EXPECT_EQ("audio-volume-medium", notev[3].app_icon);
348
 
        EXPECT_EQ("audio-volume-medium", notev[4].app_icon);
349
 
        EXPECT_EQ("audio-volume-medium", notev[5].app_icon);
350
 
        EXPECT_EQ("audio-volume-medium", notev[6].app_icon);
351
 
        EXPECT_EQ("audio-volume-high",   notev[7].app_icon);
352
 
        EXPECT_EQ("audio-volume-high",   notev[8].app_icon);
353
 
        EXPECT_EQ("audio-volume-high",   notev[9].app_icon);
354
 
        EXPECT_EQ("audio-volume-high",   notev[10].app_icon);
 
326
    auto options = optionsMock();
 
327
    auto volumeControl = volumeControlMock(options);
 
328
    auto volumeWarning = volumeWarningMock(options);
 
329
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
330
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
331
 
 
332
    /* Set an initial volume */
 
333
    notifications->clearNotifications();
 
334
    setMockVolume(volumeControl, 0.5);
 
335
    loop(50);
 
336
    auto notev = notifications->getNotifications();
 
337
    ASSERT_EQ(1, notev.size());
 
338
 
 
339
    /* Generate a set of notifications */
 
340
    notifications->clearNotifications();
 
341
    for (float i = 0.0; i < 1.01; i += 0.1) {
 
342
        setMockVolume(volumeControl, i);
 
343
    }
 
344
 
 
345
    loop(50);
 
346
    notev = notifications->getNotifications();
 
347
    ASSERT_EQ(11, notev.size());
 
348
 
 
349
    EXPECT_EQ("audio-volume-muted",  notev[0].app_icon);
 
350
    EXPECT_EQ("audio-volume-low",    notev[1].app_icon);
 
351
    EXPECT_EQ("audio-volume-low",    notev[2].app_icon);
 
352
    EXPECT_EQ("audio-volume-medium", notev[3].app_icon);
 
353
    EXPECT_EQ("audio-volume-medium", notev[4].app_icon);
 
354
    EXPECT_EQ("audio-volume-medium", notev[5].app_icon);
 
355
    EXPECT_EQ("audio-volume-medium", notev[6].app_icon);
 
356
    EXPECT_EQ("audio-volume-high",   notev[7].app_icon);
 
357
    EXPECT_EQ("audio-volume-high",   notev[8].app_icon);
 
358
    EXPECT_EQ("audio-volume-high",   notev[9].app_icon);
 
359
    EXPECT_EQ("audio-volume-high",   notev[10].app_icon);
355
360
}
356
361
 
357
362
TEST_F(NotificationsTest, ServerRestart) {
358
 
        auto options = optionsMock();
359
 
        auto volumeControl = volumeControlMock(options);
360
 
        auto volumeWarning = volumeWarningMock(options);
361
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
362
 
 
363
 
        /* Set a volume */
364
 
        notifications->clearNotifications();
365
 
        setMockVolume(volumeControl, 0.50);
366
 
        loop(50);
367
 
        auto notev = notifications->getNotifications();
368
 
        ASSERT_EQ(1, notev.size());
369
 
 
370
 
        /* Restart server without sync notifications */
371
 
        notifications->clearNotifications();
372
 
        dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
373
 
        notifications.reset();
374
 
 
375
 
        loop(50);
376
 
 
377
 
        notifications = std::make_shared<NotificationsMock>(std::vector<std::string>({"body", "body-markup", "icon-static"}));
378
 
        dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
379
 
        dbus_test_task_run((DbusTestTask*)*notifications);
380
 
 
381
 
        /* Change the volume */
382
 
        notifications->clearNotifications();
383
 
        setMockVolume(volumeControl, 0.60);
384
 
        loop(50);
385
 
        notev = notifications->getNotifications();
386
 
        ASSERT_EQ(0, notev.size());
387
 
 
388
 
        /* Put a good server back */
389
 
        dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
390
 
        notifications.reset();
391
 
 
392
 
        loop(50);
393
 
 
394
 
        notifications = std::make_shared<NotificationsMock>();
395
 
        dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
396
 
        dbus_test_task_run((DbusTestTask*)*notifications);
397
 
 
398
 
        /* Change the volume again */
399
 
        notifications->clearNotifications();
400
 
        setMockVolume(volumeControl, 0.70);
401
 
        loop(50);
402
 
        notev = notifications->getNotifications();
403
 
        ASSERT_EQ(1, notev.size());
 
363
    auto options = optionsMock();
 
364
    auto volumeControl = volumeControlMock(options);
 
365
    auto volumeWarning = volumeWarningMock(options);
 
366
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
367
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
368
 
 
369
    /* Set a volume */
 
370
    notifications->clearNotifications();
 
371
    setMockVolume(volumeControl, 0.50);
 
372
    loop(50);
 
373
    auto notev = notifications->getNotifications();
 
374
    ASSERT_EQ(1, notev.size());
 
375
 
 
376
    /* Restart server without sync notifications */
 
377
    notifications->clearNotifications();
 
378
    dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
 
379
    notifications.reset();
 
380
 
 
381
    loop(50);
 
382
 
 
383
    notifications = std::make_shared<NotificationsMock>(std::vector<std::string>({"body", "body-markup", "icon-static"}));
 
384
    dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
 
385
    dbus_test_task_run((DbusTestTask*)*notifications);
 
386
 
 
387
    /* Change the volume */
 
388
    notifications->clearNotifications();
 
389
    setMockVolume(volumeControl, 0.60);
 
390
    loop(50);
 
391
    notev = notifications->getNotifications();
 
392
    ASSERT_EQ(0, notev.size());
 
393
 
 
394
    /* Put a good server back */
 
395
    dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
 
396
    notifications.reset();
 
397
 
 
398
    loop(50);
 
399
 
 
400
    notifications = std::make_shared<NotificationsMock>();
 
401
    dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
 
402
    dbus_test_task_run((DbusTestTask*)*notifications);
 
403
 
 
404
    /* Change the volume again */
 
405
    notifications->clearNotifications();
 
406
    setMockVolume(volumeControl, 0.70);
 
407
    loop(50);
 
408
    notev = notifications->getNotifications();
 
409
    ASSERT_EQ(1, notev.size());
404
410
}
405
411
 
406
412
TEST_F(NotificationsTest, HighVolume) {
407
 
        auto options = optionsMock();
408
 
        auto volumeControl = volumeControlMock(options);
409
 
        auto volumeWarning = volumeWarningMock(options);
410
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
411
 
 
412
 
        /* Set a volume */
413
 
        notifications->clearNotifications();
414
 
        setMockVolume(volumeControl, 0.50);
415
 
        loop(50);
416
 
        auto notev = notifications->getNotifications();
417
 
        ASSERT_EQ(1, notev.size());
418
 
        EXPECT_EQ("Volume", notev[0].summary);
419
 
        EXPECT_EQ("Speakers", notev[0].body);
420
 
        EXPECT_GVARIANT_EQ("@s 'false'", notev[0].hints["x-canonical-value-bar-tint"]);
421
 
 
422
 
        /* Set high volume with volume change */
423
 
        notifications->clearNotifications();
424
 
        volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true);
425
 
        setMockVolume(volumeControl, 0.90);
426
 
        loop(50);
427
 
        notev = notifications->getNotifications();
428
 
        ASSERT_LT(0, notev.size()); /* This passes with one or two since it would just be an update to the first if a second was sent */
429
 
        EXPECT_EQ("Volume", notev[0].summary);
430
 
        EXPECT_EQ("Speakers", notev[0].body);
431
 
        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
432
 
 
433
 
        /* Move it back */
434
 
        volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), false);
435
 
        setMockVolume(volumeControl, 0.50);
436
 
        loop(50);
437
 
 
438
 
        /* Set high volume without level change */
439
 
        /* NOTE: This can happen if headphones are plugged in */
440
 
        notifications->clearNotifications();
441
 
        volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true);
442
 
        loop(50);
443
 
        notev = notifications->getNotifications();
444
 
        ASSERT_EQ(1, notev.size());
445
 
        EXPECT_EQ("Volume", notev[0].summary);
446
 
        EXPECT_EQ("Speakers", notev[0].body);
447
 
        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
 
413
    auto options = optionsMock();
 
414
    auto volumeControl = volumeControlMock(options);
 
415
    auto volumeWarning = volumeWarningMock(options);
 
416
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
417
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
418
 
 
419
    /* Set a volume */
 
420
    notifications->clearNotifications();
 
421
    setMockVolume(volumeControl, 0.50);
 
422
    loop(50);
 
423
    auto notev = notifications->getNotifications();
 
424
    ASSERT_EQ(1, notev.size());
 
425
    EXPECT_EQ("Volume", notev[0].summary);
 
426
    EXPECT_EQ("Speakers", notev[0].body);
 
427
    EXPECT_GVARIANT_EQ("@s 'false'", notev[0].hints["x-canonical-value-bar-tint"]);
 
428
 
 
429
    /* Set high volume with volume change */
 
430
    notifications->clearNotifications();
 
431
    volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true);
 
432
    setMockVolume(volumeControl, 0.90);
 
433
    loop(50);
 
434
    notev = notifications->getNotifications();
 
435
    ASSERT_LT(0, notev.size()); /* This passes with one or two since it would just be an update to the first if a second was sent */
 
436
    EXPECT_EQ("Volume", notev[0].summary);
 
437
    EXPECT_EQ("Speakers", notev[0].body);
 
438
    EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
 
439
 
 
440
    /* Move it back */
 
441
    volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), false);
 
442
    setMockVolume(volumeControl, 0.50);
 
443
    loop(50);
 
444
 
 
445
    /* Set high volume without level change */
 
446
    /* NOTE: This can happen if headphones are plugged in */
 
447
    notifications->clearNotifications();
 
448
    volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true);
 
449
    loop(50);
 
450
    notev = notifications->getNotifications();
 
451
    ASSERT_EQ(1, notev.size());
 
452
    EXPECT_EQ("Volume", notev[0].summary);
 
453
    EXPECT_EQ("Speakers", notev[0].body);
 
454
    EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
448
455
}
449
456
 
450
457
TEST_F(NotificationsTest, MenuHide) {
451
 
        auto options = optionsMock();
452
 
        auto volumeControl = volumeControlMock(options);
453
 
        auto volumeWarning = volumeWarningMock(options);
454
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
455
 
 
456
 
        /* Set a volume */
457
 
        notifications->clearNotifications();
458
 
        setMockVolume(volumeControl, 0.50);
459
 
        loop(50);
460
 
        auto notev = notifications->getNotifications();
461
 
        EXPECT_EQ(1, notev.size());
462
 
 
463
 
        /* Set the indicator to shown, and set a new volume */
464
 
        notifications->clearNotifications();
465
 
        setIndicatorShown(true);
466
 
        loop(50);
467
 
        setMockVolume(volumeControl, 0.60);
468
 
        loop(50);
469
 
        notev = notifications->getNotifications();
470
 
        EXPECT_EQ(0, notev.size());
471
 
 
472
 
        /* Set the indicator to hidden, and set a new volume */
473
 
        notifications->clearNotifications();
474
 
        setIndicatorShown(false);
475
 
        loop(50);
476
 
        setMockVolume(volumeControl, 0.70);
477
 
        loop(50);
478
 
        notev = notifications->getNotifications();
479
 
        EXPECT_EQ(1, notev.size());
 
458
    auto options = optionsMock();
 
459
    auto volumeControl = volumeControlMock(options);
 
460
    auto volumeWarning = volumeWarningMock(options);
 
461
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
462
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
463
 
 
464
    /* Set a volume */
 
465
    notifications->clearNotifications();
 
466
    setMockVolume(volumeControl, 0.50);
 
467
    loop(50);
 
468
    auto notev = notifications->getNotifications();
 
469
    EXPECT_EQ(1, notev.size());
 
470
 
 
471
    /* Set the indicator to shown, and set a new volume */
 
472
    notifications->clearNotifications();
 
473
    setIndicatorShown(true);
 
474
    loop(50);
 
475
    setMockVolume(volumeControl, 0.60);
 
476
    loop(50);
 
477
    notev = notifications->getNotifications();
 
478
    EXPECT_EQ(0, notev.size());
 
479
 
 
480
    /* Set the indicator to hidden, and set a new volume */
 
481
    notifications->clearNotifications();
 
482
    setIndicatorShown(false);
 
483
    loop(50);
 
484
    setMockVolume(volumeControl, 0.70);
 
485
    loop(50);
 
486
    notev = notifications->getNotifications();
 
487
    EXPECT_EQ(1, notev.size());
480
488
}
481
489
 
482
490
TEST_F(NotificationsTest, ExtendendVolumeNotification) {
483
 
        auto options = optionsMock();
484
 
        auto volumeControl = volumeControlMock(options);
485
 
        auto volumeWarning = volumeWarningMock(options);
486
 
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
487
 
 
488
 
        /* Set a volume */
489
 
        notifications->clearNotifications();
490
 
        setMockVolume(volumeControl, 0.50);
491
 
        loop(50);
492
 
        auto notev = notifications->getNotifications();
493
 
        ASSERT_EQ(1, notev.size());
494
 
        EXPECT_EQ("indicator-sound", notev[0].app_name);
495
 
        EXPECT_EQ("Volume", notev[0].summary);
496
 
        EXPECT_EQ(0, notev[0].actions.size());
497
 
        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
498
 
        EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]);
499
 
 
500
 
        /* Allow an amplified volume */
501
 
        notifications->clearNotifications();
502
 
        volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM);
503
 
        options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.5);
504
 
        loop(50);
505
 
        notev = notifications->getNotifications();
506
 
        ASSERT_EQ(1, notev.size());
507
 
        EXPECT_GVARIANT_EQ("@i 33", notev[0].hints["value"]);
508
 
 
509
 
        /* Set to 'over max' */
510
 
        notifications->clearNotifications();
511
 
        setMockVolume(volumeControl, 1.525);
512
 
        loop(50);
513
 
        notev = notifications->getNotifications();
514
 
        ASSERT_EQ(1, notev.size());
515
 
        EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]);
516
 
 
517
 
        /* Put back */
518
 
        notifications->clearNotifications();
519
 
        options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.0);
520
 
        loop(50);
521
 
        notev = notifications->getNotifications();
522
 
        ASSERT_EQ(1, notev.size());
523
 
        EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]);
 
491
    auto options = optionsMock();
 
492
    auto volumeControl = volumeControlMock(options);
 
493
    auto volumeWarning = volumeWarningMock(options);
 
494
    auto accountsService = std::make_shared<AccountsServiceAccess>();
 
495
    auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
496
 
 
497
    /* Set a volume */
 
498
    notifications->clearNotifications();
 
499
    setMockVolume(volumeControl, 0.50);
 
500
    loop(50);
 
501
    auto notev = notifications->getNotifications();
 
502
    ASSERT_EQ(1, notev.size());
 
503
    EXPECT_EQ("indicator-sound", notev[0].app_name);
 
504
    EXPECT_EQ("Volume", notev[0].summary);
 
505
    EXPECT_EQ(0, notev[0].actions.size());
 
506
    EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
 
507
    EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]);
 
508
 
 
509
    /* Allow an amplified volume */
 
510
    notifications->clearNotifications();
 
511
    volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM);
 
512
    options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.5);
 
513
    loop(50);
 
514
    notev = notifications->getNotifications();
 
515
    ASSERT_EQ(1, notev.size());
 
516
    EXPECT_GVARIANT_EQ("@i 33", notev[0].hints["value"]);
 
517
 
 
518
    /* Set to 'over max' */
 
519
    notifications->clearNotifications();
 
520
    setMockVolume(volumeControl, 1.525);
 
521
    loop(50);
 
522
    notev = notifications->getNotifications();
 
523
    ASSERT_EQ(1, notev.size());
 
524
    EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]);
 
525
 
 
526
    /* Put back */
 
527
    notifications->clearNotifications();
 
528
    options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.0);
 
529
    loop(50);
 
530
    notev = notifications->getNotifications();
 
531
    ASSERT_EQ(1, notev.size());
 
532
    EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]);
524
533
}
525
534
 
526
535
TEST_F(NotificationsTest, TriggerWarning) {
527
536
 
528
 
        // Tests all the conditions needed to trigger a volume warning.
529
 
        // There are many possible combinations, so this test is slow. :P
530
 
 
531
 
        const struct {
532
 
                bool expected;
533
 
                VolumeControlActiveOutput output;
534
 
        } test_outputs[] = {
535
 
                { false, VOLUME_CONTROL_ACTIVE_OUTPUT_SPEAKERS },
536
 
                { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_HEADPHONES },
537
 
                { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_HEADPHONES },
538
 
                { false, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_SPEAKER },
539
 
                { false, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_SPEAKER },
540
 
                { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_USB_HEADPHONES },
541
 
                { false, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_SPEAKER },
542
 
                { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_HEADPHONES },
543
 
                { false, VOLUME_CONTROL_ACTIVE_OUTPUT_CALL_MODE }
544
 
        };
545
 
 
546
 
        const struct {
547
 
                bool expected;
548
 
                pa_volume_t volume;
549
 
                pa_volume_t loud_volume;
550
 
        } test_volumes[] = {
551
 
                { false,   50, 100 },
552
 
                { false,   99, 100 },
553
 
                { true,   100, 100 },
554
 
                { true,   101, 100 }
555
 
        };
556
 
 
557
 
        const struct {
558
 
                bool expected;
559
 
                bool approved;
560
 
        } test_approved[] = {
561
 
                { true,  false },
562
 
                { false, true }
563
 
        };
564
 
 
565
 
        const struct {
566
 
                bool expected;
567
 
                bool warnings_enabled;
568
 
        } test_warnings_enabled[] = {
569
 
                { true,  true },
570
 
                { false, false }
571
 
        };
572
 
 
573
 
        const struct {
574
 
                bool expected;
575
 
                bool multimedia_active;
576
 
        } test_multimedia_active[] = {
577
 
                { true,  true },
578
 
                { false, false }
579
 
        };
580
 
 
581
 
        for (const auto& outputs : test_outputs) {
582
 
        for (const auto& volumes : test_volumes) {
583
 
        for (const auto& approved : test_approved) {
584
 
        for (const auto& warnings_enabled : test_warnings_enabled) {
585
 
        for (const auto& multimedia_active : test_multimedia_active) {
586
 
 
587
 
                notifications->clearNotifications();
588
 
 
589
 
                // instantiate the test subjects
590
 
                auto options = optionsMock();
591
 
                auto volumeControl = volumeControlMock(options);
592
 
                auto volumeWarning = volumeWarningMock(options);
593
 
                auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning);
594
 
 
595
 
                // run the test
596
 
                options_mock_mock_set_loud_volume(OPTIONS_MOCK(options.get()), volumes.loud_volume);
597
 
                options_mock_mock_set_loud_warning_enabled(OPTIONS_MOCK(options.get()), warnings_enabled.warnings_enabled);
598
 
                volume_warning_mock_set_approved(VOLUME_WARNING_MOCK(volumeWarning.get()), approved.approved);
599
 
                volume_warning_mock_set_multimedia_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), volumes.volume);
600
 
                volume_warning_mock_set_multimedia_active(VOLUME_WARNING_MOCK(volumeWarning.get()), multimedia_active.multimedia_active);
601
 
                volume_control_mock_mock_set_active_output(VOLUME_CONTROL_MOCK(volumeControl.get()), outputs.output);
602
 
 
603
 
                loop_until_notifications();
604
 
 
605
 
                // check the result
606
 
                auto notev = notifications->getNotifications();
607
 
                const bool warning_expected = outputs.expected && volumes.expected && approved.expected && warnings_enabled.expected && multimedia_active.expected;
608
 
                if (warning_expected) {
609
 
                        EXPECT_TRUE(volume_warning_get_active(volumeWarning.get()));
610
 
                        ASSERT_EQ(1, notev.size());
611
 
                        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-snap-decisions"]);
612
 
                        EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-private-synchronous"]);
613
 
                }
614
 
                else {
615
 
                        EXPECT_FALSE(volume_warning_get_active(volumeWarning.get()));
616
 
                        ASSERT_EQ(1, notev.size());
617
 
                        EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-snap-decisions"]);
618
 
                        EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
619
 
                }
620
 
 
621
 
        } // multimedia_active
622
 
        } // warnings_enabled
623
 
        } // approved
624
 
        } // volumes
625
 
        } // outputs
 
537
    // Tests all the conditions needed to trigger a volume warning.
 
538
    // There are many possible combinations, so this test is slow. :P
 
539
 
 
540
    const struct {
 
541
        bool expected;
 
542
        VolumeControlActiveOutput output;
 
543
    } test_outputs[] = {
 
544
        { false, VOLUME_CONTROL_ACTIVE_OUTPUT_SPEAKERS },
 
545
        { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_HEADPHONES },
 
546
        { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_HEADPHONES },
 
547
        { false, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_SPEAKER },
 
548
        { false, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_SPEAKER },
 
549
        { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_USB_HEADPHONES },
 
550
        { false, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_SPEAKER },
 
551
        { true,  VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_HEADPHONES },
 
552
        { false, VOLUME_CONTROL_ACTIVE_OUTPUT_CALL_MODE }
 
553
    };
 
554
 
 
555
    const struct {
 
556
        bool expected;
 
557
        pa_volume_t volume;
 
558
        pa_volume_t loud_volume;
 
559
    } test_volumes[] = {
 
560
        { false,   50, 100 },
 
561
        { false,   99, 100 },
 
562
        { true,   100, 100 },
 
563
        { true,   101, 100 }
 
564
    };
 
565
 
 
566
    const struct {
 
567
        bool expected;
 
568
        bool approved;
 
569
    } test_approved[] = {
 
570
        { true,  false },
 
571
        { false, true }
 
572
    };
 
573
 
 
574
    const struct {
 
575
        bool expected;
 
576
        bool warnings_enabled;
 
577
    } test_warnings_enabled[] = {
 
578
        { true,  true },
 
579
        { false, false }
 
580
    };
 
581
 
 
582
    const struct {
 
583
        bool expected;
 
584
        bool multimedia_active;
 
585
    } test_multimedia_active[] = {
 
586
        { true,  true },
 
587
        { false, false }
 
588
    };
 
589
 
 
590
    for (const auto& outputs : test_outputs) {
 
591
    for (const auto& volumes : test_volumes) {
 
592
    for (const auto& approved : test_approved) {
 
593
    for (const auto& warnings_enabled : test_warnings_enabled) {
 
594
    for (const auto& multimedia_active : test_multimedia_active) {
 
595
 
 
596
        notifications->clearNotifications();
 
597
 
 
598
        // instantiate the test subjects
 
599
        auto options = optionsMock();
 
600
        auto volumeControl = volumeControlMock(options);
 
601
        auto volumeWarning = volumeWarningMock(options);
 
602
        auto accountsService = std::make_shared<AccountsServiceAccess>();
 
603
        auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService);
 
604
 
 
605
        // run the test
 
606
        options_mock_mock_set_loud_volume(OPTIONS_MOCK(options.get()), volumes.loud_volume);
 
607
        options_mock_mock_set_loud_warning_enabled(OPTIONS_MOCK(options.get()), warnings_enabled.warnings_enabled);
 
608
        volume_warning_mock_set_approved(VOLUME_WARNING_MOCK(volumeWarning.get()), approved.approved);
 
609
        volume_warning_mock_set_multimedia_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), volumes.volume);
 
610
        volume_warning_mock_set_multimedia_active(VOLUME_WARNING_MOCK(volumeWarning.get()), multimedia_active.multimedia_active);
 
611
        volume_control_mock_mock_set_active_output(VOLUME_CONTROL_MOCK(volumeControl.get()), outputs.output);
 
612
 
 
613
        loop_until_notifications();
 
614
 
 
615
        // check the result
 
616
        auto notev = notifications->getNotifications();
 
617
        const bool warning_expected = outputs.expected && volumes.expected && approved.expected && warnings_enabled.expected && multimedia_active.expected;
 
618
        if (warning_expected) {
 
619
            EXPECT_TRUE(volume_warning_get_active(volumeWarning.get()));
 
620
            ASSERT_EQ(1, notev.size());
 
621
            EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-snap-decisions"]);
 
622
            EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-private-synchronous"]);
 
623
        }
 
624
        else {
 
625
            EXPECT_FALSE(volume_warning_get_active(volumeWarning.get()));
 
626
            ASSERT_EQ(1, notev.size());
 
627
            EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-snap-decisions"]);
 
628
            EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
 
629
        }
 
630
 
 
631
    } // multimedia_active
 
632
    } // warnings_enabled
 
633
    } // approved
 
634
    } // volumes
 
635
    } // outputs
626
636
}
627
637