2
* Copyright © 2015 Canonical Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; version 3.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Ted Gould <ted@canonical.com>
22
#include <gtest/gtest.h>
24
#include <libdbustest/dbus-test.h>
25
#include <libnotify/notify.h>
27
#include "notifications-mock.h"
28
#include "gtest-gvariant.h"
31
#include "indicator-sound-service.h"
32
#include "vala-mocks.h"
35
class NotificationsTest : public ::testing::Test
38
DbusTestService * service = NULL;
40
GDBusConnection * session = NULL;
41
std::shared_ptr<NotificationsMock> notifications;
43
virtual void SetUp() {
44
g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
45
g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
47
service = dbus_test_service_new(NULL);
48
dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SESSION);
50
/* Useful for debugging test failures, not needed all the time (until it fails) */
52
auto bustle = std::shared_ptr<DbusTestTask>([]() {
53
DbusTestTask * bustle = DBUS_TEST_TASK(dbus_test_bustle_new("notifications-test.bustle"));
54
dbus_test_task_set_name(bustle, "Bustle");
55
dbus_test_task_set_bus(bustle, DBUS_TEST_SERVICE_BUS_SESSION);
57
}(), [](DbusTestTask * bustle) {
58
g_clear_object(&bustle);
60
dbus_test_service_add_task(service, bustle.get());
63
notifications = std::make_shared<NotificationsMock>();
65
dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
66
dbus_test_service_start_tasks(service);
68
session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
69
ASSERT_NE(nullptr, session);
70
g_dbus_connection_set_exit_on_close(session, FALSE);
71
g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
73
/* This is done in main.c */
74
notify_init("indicator-sound");
77
virtual void TearDown() {
78
if (notify_is_initted())
81
notifications.reset();
82
g_clear_object(&service);
84
g_object_unref(session);
86
unsigned int cleartry = 0;
87
while (session != NULL && cleartry < 100) {
92
ASSERT_EQ(nullptr, session);
95
static gboolean timeout_cb (gpointer user_data) {
96
GMainLoop * loop = static_cast<GMainLoop *>(user_data);
97
g_main_loop_quit(loop);
98
return G_SOURCE_REMOVE;
101
void loop (unsigned int ms) {
102
GMainLoop * loop = g_main_loop_new(NULL, FALSE);
103
g_timeout_add(ms, timeout_cb, loop);
104
g_main_loop_run(loop);
105
g_main_loop_unref(loop);
108
static int unref_idle (gpointer user_data) {
109
g_variant_unref(static_cast<GVariant *>(user_data));
110
return G_SOURCE_REMOVE;
113
std::shared_ptr<MediaPlayerList> playerListMock () {
114
auto playerList = std::shared_ptr<MediaPlayerList>(
115
MEDIA_PLAYER_LIST(media_player_list_mock_new()),
116
[](MediaPlayerList * list) {
117
g_clear_object(&list);
122
std::shared_ptr<VolumeControl> volumeControlMock () {
123
auto volumeControl = std::shared_ptr<VolumeControl>(
124
VOLUME_CONTROL(volume_control_mock_new()),
125
[](VolumeControl * control){
126
g_clear_object(&control);
128
return volumeControl;
131
std::shared_ptr<IndicatorSoundService> standardService (std::shared_ptr<VolumeControl> volumeControl, std::shared_ptr<MediaPlayerList> playerList) {
132
auto soundService = std::shared_ptr<IndicatorSoundService>(
133
indicator_sound_service_new(playerList.get(), volumeControl.get(), nullptr),
134
[](IndicatorSoundService * service){
135
g_clear_object(&service);
142
TEST_F(NotificationsTest, BasicObject) {
143
auto soundService = standardService(volumeControlMock(), playerListMock());
145
/* Give some time settle */
151
TEST_F(NotificationsTest, VolumeChanges) {
152
auto volumeControl = volumeControlMock();
153
auto soundService = standardService(volumeControl, playerListMock());
156
notifications->clearNotifications();
157
volume_control_set_volume(volumeControl.get(), 0.50);
159
auto notev = notifications->getNotifications();
160
ASSERT_EQ(1, notev.size());
161
EXPECT_EQ("indicator-sound", notev[0].app_name);
162
EXPECT_EQ("Volume", notev[0].summary);
163
EXPECT_EQ(0, notev[0].actions.size());
164
EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]);
165
EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]);
167
/* Set a different volume */
168
notifications->clearNotifications();
169
volume_control_set_volume(volumeControl.get(), 0.60);
171
notev = notifications->getNotifications();
172
ASSERT_EQ(1, notev.size());
173
EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]);
175
/* Set the same volume */
176
notifications->clearNotifications();
177
volume_control_set_volume(volumeControl.get(), 0.60);
179
notev = notifications->getNotifications();
180
ASSERT_EQ(0, notev.size());
182
/* Change just a little */
183
notifications->clearNotifications();
184
volume_control_set_volume(volumeControl.get(), 0.60001);
186
notev = notifications->getNotifications();
187
ASSERT_EQ(0, notev.size());
190
TEST_F(NotificationsTest, StreamChanges) {
191
auto volumeControl = volumeControlMock();
192
auto soundService = standardService(volumeControl, playerListMock());
195
notifications->clearNotifications();
196
volume_control_set_volume(volumeControl.get(), 0.5);
198
auto notev = notifications->getNotifications();
199
ASSERT_EQ(1, notev.size());
201
/* Change Streams, no volume change */
202
notifications->clearNotifications();
203
volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "alarm");
204
volume_control_set_volume(volumeControl.get(), 0.5);
206
notev = notifications->getNotifications();
207
EXPECT_EQ(0, notev.size());
209
/* Change Streams, volume change */
210
notifications->clearNotifications();
211
volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "alert");
212
volume_control_set_volume(volumeControl.get(), 0.60);
214
notev = notifications->getNotifications();
215
EXPECT_EQ(0, notev.size());
217
/* Change Streams, no volume change, volume up */
218
notifications->clearNotifications();
219
volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "multimedia");
220
volume_control_set_volume(volumeControl.get(), 0.60);
222
volume_control_set_volume(volumeControl.get(), 0.65);
223
notev = notifications->getNotifications();
224
EXPECT_EQ(1, notev.size());
225
EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]);
228
TEST_F(NotificationsTest, IconTesting) {
229
auto volumeControl = volumeControlMock();
230
auto soundService = standardService(volumeControl, playerListMock());
232
/* Set an initial volume */
233
notifications->clearNotifications();
234
volume_control_set_volume(volumeControl.get(), 0.5);
236
auto notev = notifications->getNotifications();
237
ASSERT_EQ(1, notev.size());
239
/* Generate a set of notifications */
240
notifications->clearNotifications();
241
for (float i = 0.0; i < 1.01; i += 0.1) {
242
volume_control_set_volume(volumeControl.get(), i);
246
notev = notifications->getNotifications();
247
ASSERT_EQ(11, notev.size());
249
EXPECT_EQ("audio-volume-muted", notev[0].app_icon);
250
EXPECT_EQ("audio-volume-low", notev[1].app_icon);
251
EXPECT_EQ("audio-volume-low", notev[2].app_icon);
252
EXPECT_EQ("audio-volume-medium", notev[3].app_icon);
253
EXPECT_EQ("audio-volume-medium", notev[4].app_icon);
254
EXPECT_EQ("audio-volume-medium", notev[5].app_icon);
255
EXPECT_EQ("audio-volume-medium", notev[6].app_icon);
256
EXPECT_EQ("audio-volume-high", notev[7].app_icon);
257
EXPECT_EQ("audio-volume-high", notev[8].app_icon);
258
EXPECT_EQ("audio-volume-high", notev[9].app_icon);
259
EXPECT_EQ("audio-volume-high", notev[10].app_icon);
262
TEST_F(NotificationsTest, ServerRestart) {
263
auto volumeControl = volumeControlMock();
264
auto soundService = standardService(volumeControl, playerListMock());
267
notifications->clearNotifications();
268
volume_control_set_volume(volumeControl.get(), 0.50);
270
auto notev = notifications->getNotifications();
271
ASSERT_EQ(1, notev.size());
273
/* Restart server without sync notifications */
274
notifications->clearNotifications();
275
dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
276
notifications.reset();
280
notifications = std::make_shared<NotificationsMock>(std::vector<std::string>({"body", "body-markup", "icon-static"}));
281
dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
282
dbus_test_task_run((DbusTestTask*)*notifications);
284
/* Change the volume */
285
notifications->clearNotifications();
286
volume_control_set_volume(volumeControl.get(), 0.60);
288
notev = notifications->getNotifications();
289
ASSERT_EQ(0, notev.size());
291
/* Put a good server back */
292
dbus_test_service_remove_task(service, (DbusTestTask*)*notifications);
293
notifications.reset();
297
notifications = std::make_shared<NotificationsMock>();
298
dbus_test_service_add_task(service, (DbusTestTask*)*notifications);
299
dbus_test_task_run((DbusTestTask*)*notifications);
301
/* Change the volume again */
302
notifications->clearNotifications();
303
volume_control_set_volume(volumeControl.get(), 0.70);
305
notev = notifications->getNotifications();
306
ASSERT_EQ(1, notev.size());
309
TEST_F(NotificationsTest, HighVolume) {
310
auto volumeControl = volumeControlMock();
311
auto soundService = standardService(volumeControl, playerListMock());
314
notifications->clearNotifications();
315
volume_control_set_volume(volumeControl.get(), 0.50);
317
auto notev = notifications->getNotifications();
318
ASSERT_EQ(1, notev.size());
319
EXPECT_EQ("Volume", notev[0].summary);
320
EXPECT_EQ("", notev[0].body);
321
EXPECT_GVARIANT_EQ("@s 'false'", notev[0].hints["x-canonical-value-bar-tint"]);
323
/* Set high volume with volume change */
324
notifications->clearNotifications();
325
volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE);
326
volume_control_set_volume(volumeControl.get(), 0.90);
328
notev = notifications->getNotifications();
329
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 */
330
EXPECT_EQ("Volume", notev[0].summary);
331
EXPECT_EQ("High volume", notev[0].body);
332
EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
335
volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), FALSE);
336
volume_control_set_volume(volumeControl.get(), 0.50);
339
/* Set high volume without level change */
340
/* NOTE: This can happen if headphones are plugged in */
341
notifications->clearNotifications();
342
volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE);
344
notev = notifications->getNotifications();
345
ASSERT_EQ(1, notev.size());
346
EXPECT_EQ("Volume", notev[0].summary);
347
EXPECT_EQ("High volume", notev[0].body);
348
EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);