/*
* Copyright 2014 Canonical Ltd.
* Copyright 2021 Robert Tari
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY 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 .
*
* Authors:
* Ted Gould
* Robert Tari
*/
#include
#include
#include
#include
#include "accounts-service-mock.h"
extern "C" {
#include "indicator-sound-service.h"
#include "vala-mocks.h"
}
class AccountsServiceUserTest : public ::testing::Test
{
protected:
DbusTestService * service = NULL;
DbusTestDbusMock * mock = NULL;
GDBusConnection * session = NULL;
GDBusConnection * system = NULL;
GDBusProxy * proxy = NULL;
virtual void SetUp() {
service = dbus_test_service_new(NULL);
dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_BOTH);
AccountsServiceMock service_mock;
dbus_test_service_add_task(service, (DbusTestTask*)service_mock);
dbus_test_service_start_tasks(service);
session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
ASSERT_NE(nullptr, session);
g_dbus_connection_set_exit_on_close(session, FALSE);
g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
system = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
ASSERT_NE(nullptr, system);
g_dbus_connection_set_exit_on_close(system, FALSE);
g_object_add_weak_pointer(G_OBJECT(system), (gpointer *)&system);
proxy = g_dbus_proxy_new_sync(session,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.Accounts",
"/user",
"org.freedesktop.DBus.Properties",
NULL, NULL);
ASSERT_NE(nullptr, proxy);
}
virtual void TearDown() {
g_clear_object(&proxy);
g_clear_object(&mock);
g_clear_object(&service);
g_object_unref(session);
g_object_unref(system);
#if 0
/* Accounts Service keeps a bunch of references around so we
have to split the tests and can't check this :-( */
unsigned int cleartry = 0;
while ((session != NULL || system != NULL) && cleartry < 100) {
loop(100);
cleartry++;
}
ASSERT_EQ(nullptr, session);
ASSERT_EQ(nullptr, system);
#endif
}
static gboolean timeout_cb (gpointer user_data) {
GMainLoop * pLoop = static_cast(user_data);
g_main_loop_quit(pLoop);
return G_SOURCE_REMOVE;
}
void loop (unsigned int ms) {
GMainLoop * loop = g_main_loop_new(NULL, FALSE);
g_timeout_add(ms, timeout_cb, loop);
g_main_loop_run(loop);
g_main_loop_unref(loop);
}
static int unref_idle (gpointer user_data) {
g_variant_unref(static_cast(user_data));
return G_SOURCE_REMOVE;
}
const gchar * get_property_string (const gchar * name) {
GVariant * propval = g_dbus_proxy_call_sync(proxy,
"Get",
g_variant_new("(ss)", "org.ayatana.indicator.sound.AccountsService", name),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL
);
if (propval == nullptr) {
return nullptr;
}
/* NOTE: This is a bit of a hack, basically if main gets
called the returned string becomes invalid. But it
makes the test much easier to read :-/ */
g_idle_add(unref_idle, propval);
const gchar * ret = NULL;
GVariant * child = g_variant_get_child_value(propval, 0);
GVariant * vstr = g_variant_get_variant(child);
ret = g_variant_get_string(vstr, NULL);
g_variant_unref(vstr);
g_variant_unref(child);
return ret;
}
};
TEST_F(AccountsServiceUserTest, BasicObject) {
AccountsServiceUser * srv = accounts_service_user_new();
loop(50);
g_object_unref(srv);
}
TEST_F(AccountsServiceUserTest, SetMediaPlayer) {
MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");
MediaPlayerMock * media = MEDIA_PLAYER_MOCK(
g_object_new(TYPE_MEDIA_PLAYER_MOCK,
"mock-id", "player-id",
"mock-name", "Test Player",
"mock-state", "Playing",
"mock-is-running", TRUE,
"mock-can-raise", FALSE,
"mock-current-track", track,
NULL)
);
g_clear_object(&track);
AccountsServiceUser * srv = accounts_service_user_new();
accounts_service_user_set_player(srv, MEDIA_PLAYER(media));
loop(500);
/* Verify the values are on the other side of the bus */
EXPECT_STREQ("Test Player", get_property_string("PlayerName"));
EXPECT_STREQ("Playing", get_property_string("State"));
EXPECT_STREQ("Title", get_property_string("Title"));
EXPECT_STREQ("Artist", get_property_string("Artist"));
EXPECT_STREQ("Album", get_property_string("Album"));
EXPECT_STREQ("http://art.url", get_property_string("ArtUrl"));
/* Check changing the track info */
track = media_player_track_new("Artist-ish", "Title-like", "Psuedo Album", "http://fake.art.url");
media_player_mock_set_mock_current_track(media, track);
g_clear_object(&track);
accounts_service_user_set_player(srv, MEDIA_PLAYER(media));
loop(500);
EXPECT_STREQ("Test Player", get_property_string("PlayerName"));
EXPECT_STREQ("Playing", get_property_string("State"));
EXPECT_STREQ("Title-like", get_property_string("Title"));
EXPECT_STREQ("Artist-ish", get_property_string("Artist"));
EXPECT_STREQ("Psuedo Album", get_property_string("Album"));
EXPECT_STREQ("http://fake.art.url", get_property_string("ArtUrl"));
/* Check to ensure the state can be updated */
media_player_set_state(MEDIA_PLAYER(media), "Paused");
accounts_service_user_set_player(srv, MEDIA_PLAYER(media));
loop(500);
EXPECT_STREQ("Paused", get_property_string("State"));
g_object_unref(media);
g_object_unref(srv);
}