2
* Copyright 2013 Canonical Ltd.
5
* Charles Kerr <charles.kerr@canonical.com>
7
* This program is free software: you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License version 3, as published
9
* by the Free Software Foundation.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranties of
13
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
* PURPOSE. See the GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License along
17
* with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "gtest-mock-dbus-fixture.h"
23
#include "backend-dbus/backend-dbus.h"
29
class Users: public GTestMockDBusFixture
33
typedef GTestMockDBusFixture super;
37
GCancellable * cancellable;
38
IndicatorSessionUsers * users;
47
cancellable = g_cancellable_new ();
49
backend_get (cancellable, NULL, &users, NULL);
50
g_assert (users != 0);
52
// wait for the users added by GTestMockDBusFixture::SetUp() to show up
53
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_ADDED, 12);
57
virtual void TearDown ()
59
g_cancellable_cancel (cancellable);
60
g_clear_object (&cancellable);
61
g_clear_object (&users);
68
void compare_user (const MockUser * mu, const IndicatorSessionUser * isu, const std::string& user_state)
70
ASSERT_EQ (user_state, login1_seat->user_state (mu->uid()));
71
ASSERT_EQ (mu->uid(), isu->uid);
72
ASSERT_EQ (mu->login_frequency(), isu->login_frequency);
73
ASSERT_STREQ (mu->username(), isu->user_name);
74
ASSERT_STREQ (mu->realname(), isu->real_name);
75
ASSERT_EQ (mu->uid(), isu->uid);
76
ASSERT_EQ (user_state!="offline", isu->is_logged_in);
77
ASSERT_EQ (user_state=="active", isu->is_current_user);
80
void compare_user (const MockUser * mu, guint uid, const std::string& user_state)
82
IndicatorSessionUser * isu;
83
isu = indicator_session_users_get_user (users, uid);
84
compare_user (mu, isu, user_state);
85
indicator_session_user_free (isu);
88
void compare_user (guint uid, const std::string& user_state)
90
IndicatorSessionUser * isu = indicator_session_users_get_user (users, uid);
91
MockUser * mu = accounts->find_by_uid (uid);
92
compare_user (mu, isu, user_state);
93
indicator_session_user_free (isu);
98
void init_event_keys (size_t n)
100
expected_event_count = n;
105
wait_for_signals__timeout (gpointer name)
107
g_error ("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name);
108
return G_SOURCE_REMOVE;
112
wait_for_signals__event (IndicatorSessionUser * u G_GNUC_UNUSED,
116
Users * self = static_cast<Users*>(gself);
118
self->event_keys.push_back (uid);
120
if (self->event_keys.size() == self->expected_event_count)
121
g_main_loop_quit (self->loop);
126
std::vector<guint> event_keys;
127
size_t expected_event_count;
129
void wait_for_signals (gpointer o, const gchar * name, size_t n)
131
const int timeout_seconds = 5; // arbitrary
135
guint handler_id = g_signal_connect (o, name,
136
G_CALLBACK(wait_for_signals__event),
138
gulong timeout_id = g_timeout_add_seconds (timeout_seconds,
139
wait_for_signals__timeout,
141
g_main_loop_run (loop);
142
g_source_remove (timeout_id);
143
g_signal_handler_disconnect (o, handler_id);
152
* Confirm that the fixture's SetUp() and TearDown() work
154
TEST_F (Users, HelloWorld)
160
* Confirm that 'users' can get the cached users from our Mock Accounts
162
TEST_F (Users, InitialUsers)
165
GList * uids = indicator_session_users_get_uids (users);
167
ASSERT_EQ (12, g_list_length (uids));
169
for (l=uids; l!=NULL; l=l->next)
171
const guint uid = GPOINTER_TO_UINT (l->data);
172
compare_user (uid, login1_seat->user_state (uid));
179
* Confirm that 'users' can tell when a new user is added
181
TEST_F (Users, UserAdded)
185
mu = new MockUser (loop, conn, "pcushing", "Peter Cushing", 2);
186
accounts->add_user (mu);
187
ASSERT_EQ (0, event_keys.size());
188
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_ADDED, 1);
189
ASSERT_EQ (1, event_keys.size());
190
compare_user (mu, event_keys[0], "offline");
194
* Confirm that 'users' can tell when a user is removed
196
TEST_F (Users, UserRemoved)
198
MockUser * mu = accounts->find_by_username ("pdavison");
200
/* confirm that users knows about pdavison */
201
IndicatorSessionUser * isu = indicator_session_users_get_user (users, mu->uid());
202
ASSERT_TRUE (isu != NULL);
203
compare_user (mu, isu, "offline");
204
g_clear_pointer (&isu, indicator_session_user_free);
206
/* on the bus, remove pdavison. */
207
accounts->remove_user (mu);
209
/* now, users should emit a 'user removed' signal... */
210
ASSERT_EQ (0, event_keys.size());
211
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_REMOVED, 1);
212
ASSERT_EQ (1, event_keys.size());
214
/* confirm that users won't give us pdavison's info */
215
isu = indicator_session_users_get_user (users, mu->uid());
216
ASSERT_TRUE (isu == NULL);
218
/* confirm that users won't give us pdavison's uid */
219
GList * uids = indicator_session_users_get_uids (users);
220
ASSERT_TRUE (g_list_find (uids, GUINT_TO_POINTER(mu->uid())) == NULL);
227
* Confirm that 'users' notices when a user's real name changes
229
TEST_F (Users, RealnameChanged)
233
mu = accounts->find_by_username ("pdavison");
234
const char * const realname = "Peter M. G. Moffett";
235
mu->set_realname (realname);
236
ASSERT_NE (mu->realname(), realname);
237
ASSERT_STREQ (mu->realname(), realname);
238
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1);
239
ASSERT_EQ (1, event_keys.size());
240
compare_user (mu, event_keys[0], "offline");
244
* Confirm that 'users' notices when users log in and out
246
TEST_F (Users, LogInLogOut)
248
// The fist doctor logs in.
249
// Confirm that 'users' notices.
250
MockUser * mu = accounts->find_by_username ("whartnell");
251
ASSERT_EQ (login1_seat->user_state (mu->uid()), "offline");
252
const int session_tag = login1_manager->add_session (login1_seat, mu);
253
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1);
254
ASSERT_EQ (1, event_keys.size());
255
compare_user (mu, event_keys[0], "online");
257
// The first doctor logs out.
258
// Confirm that 'users' notices.
259
login1_manager->remove_session (login1_seat, session_tag);
260
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1);
261
ASSERT_EQ (1, event_keys.size());
262
compare_user (mu, event_keys[0], "offline");
266
* Confirm that 'users' notices when the active session changes
268
TEST_F (Users, ActivateSession)
270
// confirm preconditions: msmith is active, msmith is offline
271
MockUser * const whartnell = accounts->find_by_username ("whartnell");
272
ASSERT_EQ (login1_seat->user_state (whartnell->uid()), "offline");
273
MockUser * const msmith = accounts->find_by_username ("msmith");
274
ASSERT_EQ (login1_seat->user_state (msmith->uid()), "active");
276
// whartnell logs in... confirm that 'users' notices
277
login1_manager->add_session (login1_seat, whartnell);
278
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1);
279
ASSERT_EQ (1, event_keys.size());
280
compare_user (whartnell, event_keys[0], "online");
282
// activate whartnell's session... confirm that 'users' sees:
283
// 1. msmith changes from 'active' to 'online'
284
// 2. whartnell changes from 'online' to 'active'
285
login1_seat->switch_to_user (whartnell->username());
286
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2);
287
ASSERT_EQ (2, event_keys.size());
288
compare_user (msmith, event_keys[0], "online");
289
compare_user (whartnell, event_keys[1], "active");
292
login1_seat->switch_to_user (msmith->username());
293
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2);
294
ASSERT_EQ (2, event_keys.size());
295
compare_user (whartnell, event_keys[0], "online");
296
compare_user (msmith, event_keys[1], "active");
300
* Confirm that we can change the active session via users' API.
301
* This is nearly the same as ActivateSession but uses users' API
303
TEST_F (Users, ActivateUser)
305
// confirm preconditions: msmith is active, msmith is offline
306
MockUser * const whartnell = accounts->find_by_username ("whartnell");
307
ASSERT_EQ (login1_seat->user_state (whartnell->uid()), "offline");
308
MockUser * const msmith = accounts->find_by_username ("msmith");
309
ASSERT_EQ (login1_seat->user_state (msmith->uid()), "active");
311
// whartnell logs in... confirm that 'users' notices
312
login1_manager->add_session (login1_seat, whartnell);
313
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1);
314
ASSERT_EQ (1, event_keys.size());
315
compare_user (whartnell, event_keys[0], "online");
317
// activate whartnell's session... confirm that 'users' sees:
318
// 1. msmith changes from 'active' to 'online'
319
// 2. whartnell changes from 'online' to 'active'
320
indicator_session_users_activate_user (users, whartnell->uid());
321
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2);
322
ASSERT_EQ (2, event_keys.size());
323
compare_user (msmith, event_keys[0], "online");
324
compare_user (whartnell, event_keys[1], "active");
327
indicator_session_users_activate_user (users, msmith->uid());
328
wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2);
329
ASSERT_EQ (2, event_keys.size());
330
compare_user (whartnell, event_keys[0], "online");
331
compare_user (msmith, event_keys[1], "active");
335
* Confirm that adding a Guest doesn't show up in the users list
337
TEST_F (Users, UnwantedGuest)
341
uids = indicator_session_users_get_uids (users);
342
const size_t n = g_list_length (uids);
345
MockUser * mu = new MockUser (loop, conn, "guest-jjbEVV", "Guest", 1);
346
mu->set_system_account (true);
347
accounts->add_user (mu);
350
uids = indicator_session_users_get_uids (users);
351
ASSERT_EQ (n, g_list_length (uids));
357
* Confirm that we can detect live sessions
359
TEST_F (Users, LiveSession)
363
// not initially a live session
364
ASSERT_FALSE (indicator_session_users_is_live_session (users));
365
g_object_get (users, INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION, &b, NULL);
368
// now add the criteria for a live session
369
MockUser * live_user = new MockUser (loop, conn, "ubuntu", "Ubuntu", 1, 999);
370
live_user->set_system_account (true);
371
accounts->add_user (live_user);
372
const int session_tag = login1_manager->add_session (login1_seat, live_user);
374
login1_seat->activate_session (session_tag);
375
wait_for_signal (users, "notify::" INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION);
377
// confirm the backend thinks it's a live session
378
ASSERT_TRUE (indicator_session_users_is_live_session (users));
379
g_object_get (users, INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION, &b, NULL);