17
17
with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include <glib-object.h>
24
#include <gtest/gtest.h>
26
#include "shared-names.h"
20
#include "gtest-dbus-fixture.h"
22
#include "backend-mock.h"
23
#include "backend-mock-users.h"
24
#include "backend-mock-guest.h"
25
#include "backend-mock-actions.h"
32
#define INDICATOR_SERVICE_OBJECT_PATH "/org/ayatana/indicator/service"
33
#define INDICATOR_SERVICE_INTERFACE_NAME "org.ayatana.indicator.service"
35
class ClientTest : public ::testing::Test
39
GTestDBus * test_dbus;
40
GDBusConnection * session_bus;
41
GMainLoop * main_loop;
49
static bool first_run = true;
52
g_setenv ("INDICATOR_SERVICE_SHUTDOWN_TIMEOUT", "1000", TRUE);
53
g_unsetenv ("INDICATOR_ALLOW_NO_WATCHERS");
54
g_unsetenv ("INDICATOR_SERVICE_REPLACE_MODE");
55
g_setenv ("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
56
g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
60
main_loop = g_main_loop_new (NULL, FALSE);
61
// pull up a test dbus that's pointed at our test .service file
62
test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
63
g_debug (G_STRLOC" service dir path is \"%s\"", INDICATOR_SERVICE_DIR);
64
g_test_dbus_add_service_dir (test_dbus, INDICATOR_SERVICE_DIR);
66
// allow the service to exist w/o a sync indicator
67
g_setenv ("INDICATOR_ALLOW_NO_WATCHERS", "1", TRUE);
69
g_test_dbus_up (test_dbus);
70
g_debug (G_STRLOC" this test bus' address is \"%s\"", g_test_dbus_get_bus_address(test_dbus));
71
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
72
g_debug (G_STRLOC" the dbus connection %p unique name is \"%s\"", session_bus, g_dbus_connection_get_unique_name(session_bus));
73
g_debug (G_STRLOC" the dbus connection %p refcount is %d", session_bus, G_OBJECT(session_bus)->ref_count);
77
virtual void TearDown()
79
g_clear_object (&session_bus);
80
g_debug (G_STRLOC" tearing down the bus");
81
g_test_dbus_down (test_dbus);
82
g_clear_object (&test_dbus);
83
g_clear_pointer (&main_loop, g_main_loop_unref);
35
dump_menu_model (GMenuModel * model, int depth)
37
GString * indent = g_string_new_len (" ", (depth*4));
38
const int n = g_menu_model_get_n_items (model);
39
g_message ("%s depth[%d] menu model[%p] has %d items", indent->str, depth, (void*)model, n);
41
for (int i=0; i<n; ++i)
44
GMenuModel * link_value;
45
GVariant * attribute_value;
47
GMenuAttributeIter * attribute_iter = g_menu_model_iterate_item_attributes (model, i);
48
while (g_menu_attribute_iter_get_next (attribute_iter, &name, &attribute_value))
50
char * str = g_variant_print (attribute_value, TRUE);
51
g_message ("%s depth[%d] menu model[%p] item[%d] attribute key[%s] value[%s]", indent->str, depth, (void*)model, i, name, str);
53
g_variant_unref (attribute_value);
55
g_clear_object (&attribute_iter);
57
GMenuLinkIter * link_iter = g_menu_model_iterate_item_links (model, i);
58
while (g_menu_link_iter_get_next (link_iter, &name, &link_value))
60
g_message ("%s depth[%d] menu model[%p] item[%d] attribute key[%s] model[%p]", indent->str, depth, (void*)model, i, name, (void*)link_value);
61
dump_menu_model (link_value, depth+1);
62
g_object_unref (link_value);
64
g_clear_object (&link_iter);
66
g_string_free (indent, TRUE);
72
/* cppcheck-suppress noConstructor */
73
class ServiceTest: public GTestDBusFixture
75
typedef GTestDBusFixture super;
77
enum { TIME_LIMIT_SEC = 10 };
81
static void on_name_appeared (GDBusConnection * connection G_GNUC_UNUSED,
82
const gchar * name G_GNUC_UNUSED,
83
const gchar * name_owner G_GNUC_UNUSED,
86
g_main_loop_quit (static_cast<ServiceTest*>(gself)->loop);
89
GSList * menu_references;
91
bool any_item_changed;
93
static void on_items_changed (GMenuModel * model G_GNUC_UNUSED,
94
gint position G_GNUC_UNUSED,
95
gint removed G_GNUC_UNUSED,
96
gint added G_GNUC_UNUSED,
97
gpointer any_item_changed)
99
*((gboolean*)any_item_changed) = true;
104
void activate_subtree (GMenuModel * model)
106
// query the GDBusMenuModel for information to activate it
107
int n = g_menu_model_get_n_items (model);
110
// give the model a moment to populate its info
112
n = g_menu_model_get_n_items (model);
115
// keep a ref so that it stays activated
116
menu_references = g_slist_prepend (menu_references, g_object_ref(model));
118
g_signal_connect (model, "items-changed", G_CALLBACK(on_items_changed), &any_item_changed);
121
for (int i=0; i<n; ++i)
124
GMenuLinkIter * iter = g_menu_model_iterate_item_links (model, i);
125
while (g_menu_link_iter_get_next (iter, NULL, &link))
127
activate_subtree (link);
128
g_object_unref (link);
130
g_clear_object (&iter);
134
void sync_menu (void)
136
g_slist_free_full (menu_references, (GDestroyNotify)g_object_unref);
137
menu_references = NULL;
138
activate_subtree (G_MENU_MODEL (menu_model));
141
GDBusMenuModel * menu_model;
142
GDBusActionGroup * action_group;
143
IndicatorSessionService * service;
145
GSettings * indicator_settings;
147
virtual void SetUp ()
151
menu_references = NULL;
152
any_item_changed = NULL;
154
timer = g_timer_new ();
155
mock_settings = g_settings_new ("com.canonical.indicator.session.backendmock");
156
mock_actions = indicator_session_actions_mock_new ();
157
mock_users = indicator_session_users_mock_new ();
158
mock_guest = indicator_session_guest_mock_new ();
159
indicator_settings = g_settings_new ("com.canonical.indicator.session");
161
// Start an IndicatorSessionService and wait for it to appear on the bus.
162
// This way our calls to g_dbus_*_get() in the next paragraph won't activate
163
// a second copy of the service...
164
service = indicator_session_service_new ();
166
// wait for the service to show up on the bus
167
const guint watch_id = g_bus_watch_name_on_connection (conn,
168
"com.canonical.indicator.session",
169
G_BUS_NAME_WATCHER_FLAGS_NONE,
170
on_name_appeared, // quits the loop
172
const guint timer_id = g_timeout_add_seconds (TIME_LIMIT_SEC, (GSourceFunc)g_main_loop_quit, loop);
173
g_main_loop_run (loop);
174
g_source_remove (timer_id);
175
g_bus_unwatch_name (watch_id);
176
ASSERT_FALSE (times_up());
178
// get the actions & menus that the service exported.
179
action_group = g_dbus_action_group_get (conn,
180
"com.canonical.indicator.session",
181
"/com/canonical/indicator/session");
182
menu_model = g_dbus_menu_model_get (conn,
183
"com.canonical.indicator.session",
184
"/com/canonical/indicator/session/desktop");
185
// the actions are added asynchronously, so wait for the actions
186
if (!g_action_group_has_action (G_ACTION_GROUP(action_group), "about"))
187
wait_for_signal (action_group, "action-added");
188
// activate all the groups in the menu so it'll be ready when we need it
189
g_signal_connect (menu_model, "items-changed", G_CALLBACK(on_items_changed), &any_item_changed);
193
virtual void TearDown ()
195
g_clear_pointer (&timer, g_timer_destroy);
197
g_slist_free_full (menu_references, (GDestroyNotify)g_object_unref);
198
menu_references = NULL;
199
g_clear_object (&menu_model);
201
g_clear_object (&action_group);
202
g_clear_object (&mock_settings);
203
g_clear_object (&indicator_settings);
204
g_clear_object (&service);
205
g_clear_object (&mock_actions);
206
g_clear_object (&mock_users);
207
g_clear_object (&mock_guest);
210
super :: TearDown ();
215
bool times_up () const
217
return g_timer_elapsed (timer, NULL) >= TIME_LIMIT_SEC;
220
void wait_for_has_action (const char * name)
222
while (!g_action_group_has_action (G_ACTION_GROUP(action_group), name) && !times_up())
225
ASSERT_FALSE (times_up());
226
ASSERT_TRUE (g_action_group_has_action (G_ACTION_GROUP(action_group), name));
229
void wait_for_menu_resync (void)
231
any_item_changed = false;
232
while (!times_up() && !any_item_changed)
239
void check_last_command_is (const char * expected)
241
char * str = g_settings_get_string (mock_settings, "last-command");
242
ASSERT_STREQ (expected, str);
246
void test_simple_action (const char * action_name)
248
wait_for_has_action (action_name);
250
g_action_group_activate_action (G_ACTION_GROUP (action_group), action_name, NULL);
251
wait_for_signal (mock_settings, "changed::last-command");
252
check_last_command_is (action_name);
257
bool find_menu_item_for_action (const char * action_key, GMenuModel ** setme, int * item_index)
259
bool success = false;
261
for (GSList * l=menu_references; !success && (l!=NULL); l=l->next)
263
GMenuModel * mm = G_MENU_MODEL (l->data);
264
const int n = g_menu_model_get_n_items (mm);
266
for (int i=0; !success && i<n; ++i)
268
char * action = NULL;
269
if (!g_menu_model_get_item_attribute (mm, i, G_MENU_ATTRIBUTE_ACTION, "s", &action))
272
if ((success = !g_strcmp0 (action, action_key)))
275
*setme = G_MENU_MODEL (g_object_ref (G_OBJECT(mm)));
277
if (item_index != NULL)
288
bool action_menuitem_exists (const char * action_name)
291
GMenuModel * model = 0;
294
if ((found = find_menu_item_for_action (action_name, &model, &pos)))
295
g_object_unref (G_OBJECT(model));
300
bool action_menuitem_label_is_ellipsized (const char * action_name)
303
GMenuModel * model = 0;
304
bool ellipsized = false;
307
if (find_menu_item_for_action (action_name, &model, &pos))
309
g_menu_model_get_item_attribute (model, pos, G_MENU_ATTRIBUTE_LABEL, "s", &label);
310
g_object_unref (G_OBJECT(model));
313
ellipsized = (label != NULL) && g_str_has_suffix (label, "\342\200\246");
318
void check_header (const char * expected_label, const char * expected_icon, const char * expected_a11y)
321
const gchar * label = NULL;
322
const gchar * icon = NULL;
323
const gchar * a11y = NULL;
326
variant = g_action_group_get_action_state (G_ACTION_GROUP(action_group), "_header");
327
g_variant_get (variant, "(&s&s&sb)", &label, &icon, &a11y, &visible);
329
if (expected_label != NULL)
330
ASSERT_STREQ (expected_label, label);
332
if (expected_icon != NULL)
333
ASSERT_STREQ (expected_icon, icon);
335
if (expected_a11y != NULL)
336
ASSERT_STREQ (expected_a11y, a11y);
338
// the session menu is always visible...
339
ASSERT_TRUE (visible);
341
g_variant_unref (variant);
344
void check_label (const char * expected_label, GMenuModel * model, int pos)
347
ASSERT_TRUE (g_menu_model_get_item_attribute (model, pos, G_MENU_ATTRIBUTE_LABEL, "s", &label));
348
ASSERT_STREQ (expected_label, label);
358
TEST_F (ServiceTest, HelloWorld)
364
TEST_F (ServiceTest, About)
366
test_simple_action ("about");
369
TEST_F (ServiceTest, Help)
371
test_simple_action ("help");
374
TEST_F (ServiceTest, Hibernate)
376
test_simple_action ("hibernate");
379
TEST_F (ServiceTest, Settings)
381
test_simple_action ("settings");
384
TEST_F (ServiceTest, Logout)
386
test_simple_action ("logout");
389
TEST_F (ServiceTest, PowerOff)
391
test_simple_action ("power-off");
394
TEST_F (ServiceTest, Reboot)
396
test_simple_action ("reboot");
399
TEST_F (ServiceTest, SwitchToScreensaver)
401
test_simple_action ("switch-to-screensaver");
404
TEST_F (ServiceTest, SwitchToGuest)
406
test_simple_action ("switch-to-guest");
409
TEST_F (ServiceTest, SwitchToGreeter)
411
test_simple_action ("switch-to-greeter");
414
TEST_F (ServiceTest, Suspend)
416
test_simple_action ("suspend");
423
find_menu_item_for_action (GMenuModel * top, const char * action_key, GMenuModel ** setme, int * item_index)
425
gboolean success = FALSE;
426
const int n = g_menu_model_get_n_items (top);
428
for (int i=0; !success && i<n; ++i)
430
char * action = NULL;
431
if (g_menu_model_get_item_attribute (top, i, G_MENU_ATTRIBUTE_ACTION, "s", &action))
433
if ((success = !g_strcmp0 (action, action_key)))
435
*setme = G_MENU_MODEL (g_object_ref (G_OBJECT(top)));
442
const char * name = NULL;
443
GMenuModel * link_value = NULL;
444
GMenuLinkIter * link_iter = g_menu_model_iterate_item_links (top, i);
445
while (!success && g_menu_link_iter_get_next (link_iter, &name, &link_value))
447
success = find_menu_item_for_action (link_value, action_key, setme, item_index);
448
g_object_unref (link_value);
450
g_clear_object (&link_iter);
457
get_menu_label_for_action (GMenuModel * top, const char * action)
461
gchar * label = NULL;
463
if (find_menu_item_for_action (top, action, &model, &pos))
465
g_menu_model_get_item_attribute (model, pos, G_MENU_ATTRIBUTE_LABEL, "s", &label);
466
g_object_unref (G_OBJECT(model));
472
gboolean str_is_ellipsized (const char * str)
474
g_assert (str != NULL);
475
return g_str_has_suffix (str, "\342\200\246");
480
TEST_F (ServiceTest, ConfirmationDisabledByBackend)
482
const char * const confirm_supported_key = "can-prompt";
483
const char * const confirm_disabled_key = "suppress-logout-restart-shutdown";
485
bool confirm_supported = g_settings_get_boolean (mock_settings, confirm_supported_key);
486
bool confirm_disabled = g_settings_get_boolean (indicator_settings, confirm_disabled_key);
487
bool confirm = confirm_supported && !confirm_disabled;
489
// confirm that the ellipsis are correct
490
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.switch-to-greeter"));
491
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.logout"));
492
if (action_menuitem_exists ("indicator.reboot"))
493
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.reboot"));
494
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.power-off"));
496
// now toggle the can-prompt flag
497
confirm_supported = !confirm_supported;
498
g_settings_set_boolean (mock_settings, confirm_supported_key, confirm_supported);
499
confirm = confirm_supported && !confirm_disabled;
501
wait_for_menu_resync ();
503
// confirm that the ellipsis are correct
504
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.switch-to-greeter"));
505
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.logout"));
506
if (action_menuitem_exists ("indicator.reboot"))
507
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.reboot"));
508
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.power-off"));
511
g_settings_reset (mock_settings, confirm_supported_key);
514
TEST_F (ServiceTest, ConfirmationDisabledByUser)
516
const char * const confirm_supported_key = "can-prompt";
517
const char * const confirm_disabled_key = "suppress-logout-restart-shutdown";
519
bool confirm_supported = g_settings_get_boolean (mock_settings, confirm_supported_key);
520
bool confirm_disabled = g_settings_get_boolean (indicator_settings, confirm_disabled_key);
521
bool confirm = confirm_supported && !confirm_disabled;
523
// confirm that the ellipsis are correct
524
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.switch-to-greeter"));
525
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.logout"));
526
if (action_menuitem_exists ("indicator.reboot"))
527
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.reboot"));
528
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.power-off"));
530
// now toggle the can-prompt flag
531
confirm_disabled = !confirm_disabled;
532
g_settings_set_boolean (indicator_settings, confirm_disabled_key, confirm_disabled);
533
confirm = confirm_supported && !confirm_disabled;
535
wait_for_menu_resync ();
537
// confirm that the ellipsis are correct
538
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.switch-to-greeter"));
539
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.logout"));
540
if (action_menuitem_exists ("indicator.reboot"))
541
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.reboot"));
542
ASSERT_EQ (confirm, action_menuitem_label_is_ellipsized ("indicator.power-off"));
545
g_settings_reset (indicator_settings, confirm_disabled_key);
92
* This is a basic test to see if we can launch indicator-session-service
93
* and call its "GetUserRealName" method. The test succeeds if we can launch
94
* the service, call the method, and get response that equals g_get_real_name().
96
* (You may be wondering why GetUserRealName() exists at all, instead of clients
97
* using g_get_real_name(). It's because the former updates itslef when the user
98
* edits his real name, while the latter returns its cached copy of the old name.)
549
* Check that the default menu has items for each of these actions
100
TEST_F (ClientTest, TestCanStartService)
106
// call GetUserRealName(), which as a side effect should activate
107
// indicator-session-service via the .service file in the tests/ directory
109
result = g_dbus_connection_call_sync (session_bus,
110
INDICATOR_SESSION_DBUS_NAME,
111
INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
112
INDICATOR_SESSION_SERVICE_DBUS_IFACE,
115
G_VARIANT_TYPE("(s)"),
116
G_DBUS_CALL_FLAGS_NONE,
121
EXPECT_TRUE (error == NULL);
122
ASSERT_TRUE (result != NULL);
126
g_warning ("GetUserRealName failed: %s", error->message);
127
g_clear_error (&error);
131
g_variant_get (result, "(&s)", &name);
132
ASSERT_STREQ (g_get_real_name(), name);
133
g_clear_pointer (&result, g_variant_unref);
135
// call IndicatorService's Shutdown() method for a clean exit
136
result = g_dbus_connection_call_sync (session_bus,
137
INDICATOR_SESSION_DBUS_NAME,
138
"/org/ayatana/indicator/service",
139
"org.ayatana.indicator.service",
142
G_DBUS_CALL_FLAGS_NONE,
144
g_clear_pointer (&result, g_variant_unref);
551
TEST_F (ServiceTest, DefaultMenuItems)
553
ASSERT_TRUE (find_menu_item_for_action ("indicator.about", NULL, NULL));
554
ASSERT_TRUE (find_menu_item_for_action ("indicator.help", NULL, NULL));
555
ASSERT_TRUE (find_menu_item_for_action ("indicator.settings", NULL, NULL));
556
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", NULL, NULL));
557
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-guest", NULL, NULL));
558
ASSERT_TRUE (find_menu_item_for_action ("indicator.logout", NULL, NULL));
559
ASSERT_TRUE (find_menu_item_for_action ("indicator.suspend", NULL, NULL));
560
ASSERT_TRUE (find_menu_item_for_action ("indicator.hibernate", NULL, NULL));
561
ASSERT_TRUE (find_menu_item_for_action ("indicator.power-off", NULL, NULL));
564
TEST_F (ServiceTest, OnlineAccountError)
568
GMenuModel * model = 0;
569
const char * const error_key = "has-online-account-error";
571
// check the initial default header state
572
check_header ("", "system-devices-panel", "System");
574
// check that the menuitems' existence matches the error flag
575
err = g_settings_get_boolean (mock_settings, error_key);
577
ASSERT_EQ (err, find_menu_item_for_action ("indicator.online-accounts", &model, &pos));
578
g_clear_object (&model);
580
// now toggle the error flag
582
g_settings_set_boolean (mock_settings, error_key, err);
584
// wait for the _header action and error menuitem to update
585
wait_for_menu_resync ();
587
// check that the menuitems' existence matches the error flag
588
ASSERT_TRUE (g_settings_get_boolean (mock_settings, error_key));
589
ASSERT_TRUE (find_menu_item_for_action ("indicator.online-accounts", &model, &pos));
590
g_clear_object (&model);
592
// check that the service has a corresponding action
593
ASSERT_TRUE (g_action_group_has_action (G_ACTION_GROUP(action_group), "online-accounts"));
594
ASSERT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP(action_group), "online-accounts"));
596
// confirm that activating the action is handled by the service
597
g_action_group_activate_action (G_ACTION_GROUP(action_group), "online-accounts", NULL);
598
wait_for_signal (mock_settings, "changed::last-command");
599
check_last_command_is ("online-accounts");
601
// check that the header's icon and a11y adjusted to the error state
602
check_header ("", "system-devices-panel-alert", "System (Attention Required)");
605
g_settings_reset (mock_settings, error_key);
610
gboolean set_live_session_to_true (gpointer unused G_GNUC_UNUSED)
612
const char * const live_session_key = "is-live-session";
613
g_settings_set_boolean (mock_settings, live_session_key, true);
614
return G_SOURCE_REMOVE;
618
TEST_F (ServiceTest, LiveSession)
621
const char * const live_session_key = "is-live-session";
623
// default BackendMock is not a live session
624
ASSERT_FALSE (g_settings_get_boolean (mock_settings, live_session_key));
625
g_object_get (mock_users, INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION, &b, NULL);
628
// confirm that we can see live sessions
629
g_idle_add (set_live_session_to_true, NULL);
630
wait_for_signal (mock_users, "notify::" INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION);
631
ASSERT_TRUE (g_settings_get_boolean (mock_settings, live_session_key));
633
g_object_get (mock_users, INDICATOR_SESSION_USERS_PROP_IS_LIVE_SESSION, &b, NULL);
637
g_settings_reset (mock_settings, live_session_key);
641
TEST_F (ServiceTest, User)
643
const char * const error_key = "has-online-account-error";
644
const char * const show_name_key = "show-real-name-on-panel";
648
guint64 login_frequency;
649
const gchar * user_name;
650
const gchar * real_name;
652
{ 101, 134, "whartnell", "First Doctor" },
653
{ 102, 119, "ptroughton", "Second Doctor" },
654
{ 103, 128, "jpertwee", "Third Doctor" },
655
{ 104, 172, "tbaker", "Fourth Doctor" },
656
{ 105, 69, "pdavison", "Fifth Doctor" },
657
{ 106, 31, "cbaker", "Sixth Doctor" },
658
{ 107, 42, "smccoy", "Seventh Doctor" },
659
{ 108, 1, "pmcgann", "Eigth Doctor" },
660
{ 109, 13, "ceccleston", "Ninth Doctor" },
661
{ 110, 47, "dtennant", "Tenth Doctor" },
662
{ 111, 34, "msmith", "Eleventh Doctor" },
663
{ 201, 1, "rhurndall", "First Doctor" }
666
// Find the switcher menu model.
667
// In BackendMock's default setup, it will only two menuitems: greeter & guest
669
GMenuModel * switch_menu = 0;
670
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
672
ASSERT_EQ (2, g_menu_model_get_n_items (switch_menu));
673
g_clear_object (&switch_menu);
675
// now add some users
676
IndicatorSessionUser * users[12];
677
for (int i=0; i<12; ++i)
679
for (int i=0; i<5; ++i)
681
IndicatorSessionUser * u = g_new0 (IndicatorSessionUser, 1);
682
u->is_current_user = false;
683
u->is_logged_in = false;
684
u->uid = account_info[i].uid;
685
u->login_frequency = account_info[i].login_frequency;
686
u->user_name = g_strdup (account_info[i].user_name);
687
u->real_name = g_strdup (account_info[i].real_name);
688
indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u);
692
wait_for_menu_resync ();
694
// now there should be 7 menuitems: greeter + guest + the five doctors
695
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
697
ASSERT_EQ (7, g_menu_model_get_n_items (switch_menu));
698
// confirm that the doctor names are sorted
699
check_label ("Fifth Doctor", switch_menu, 2);
700
check_label ("First Doctor", switch_menu, 3);
701
check_label ("Fourth Doctor", switch_menu, 4);
702
check_label ("Second Doctor", switch_menu, 5);
703
check_label ("Third Doctor", switch_menu, 6);
704
g_clear_object (&switch_menu);
706
// now remove a couple of 'em
707
indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[3].uid);
708
indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[4].uid);
710
wait_for_menu_resync ();
712
// now there should be 5 menuitems: greeter + guest + the three doctors
713
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
715
ASSERT_EQ (5, g_menu_model_get_n_items (switch_menu));
716
// confirm that the doctor names are sorted
717
check_label ("First Doctor", switch_menu, 2);
718
check_label ("Second Doctor", switch_menu, 3);
719
check_label ("Third Doctor", switch_menu, 4);
720
g_clear_object (&switch_menu);
722
// now let's have the third one be the current user
723
users[2]->is_current_user = true;
724
users[2]->is_logged_in = true;
725
indicator_session_users_changed (mock_users, users[2]->uid);
727
wait_for_menu_resync ();
729
// now there should be 5 menuitems: greeter + guest + the three doctors
730
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
732
ASSERT_EQ (5, g_menu_model_get_n_items (switch_menu));
733
g_clear_object (&switch_menu);
735
// oh hey, while we've got an active user let's check the header
736
ASSERT_FALSE (g_settings_get_boolean (indicator_settings, show_name_key));
737
ASSERT_FALSE (g_settings_get_boolean (mock_settings, error_key));
738
check_header ("", "system-devices-panel", "System");
739
g_settings_set_boolean (indicator_settings, show_name_key, true);
740
wait_for_signal (action_group, "action-state-changed");
741
check_header ("Third Doctor", "system-devices-panel", "System, Third Doctor");
742
g_settings_set_boolean (mock_settings, error_key, true);
743
wait_for_signal (action_group, "action-state-changed");
744
check_header ("Third Doctor", "system-devices-panel-alert", "System, Third Doctor (Attention Required)");
745
g_settings_reset (mock_settings, error_key);
746
g_settings_reset (indicator_settings, show_name_key);
747
wait_for_menu_resync ();
749
// try setting the max user count to 2...
750
// since troughton has the fewest logins, he should get culled
751
g_object_set (service, "max-users", 2, NULL);
753
g_object_get (service, "max-users", &max_users, NULL);
754
ASSERT_EQ (2, max_users);
755
wait_for_menu_resync ();
756
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
758
ASSERT_EQ (4, g_menu_model_get_n_items (switch_menu));
759
check_label ("First Doctor", switch_menu, 2);
760
check_label ("Third Doctor", switch_menu, 3);
761
g_clear_object (&switch_menu);
763
// add some more, test sorting and culling.
764
// add in all the doctors, but only show 7, and make msmith the current session
765
g_object_set (service, "max-users", 7, NULL);
766
g_object_get (service, "max-users", &max_users, NULL);
767
ASSERT_EQ (7, max_users);
768
for (int i=3; i<12; ++i)
770
IndicatorSessionUser * u = g_new0 (IndicatorSessionUser, 1);
771
u->is_current_user = false;
772
u->is_logged_in = false;
774
u->login_frequency = account_info[i].login_frequency;
775
u->user_name = g_strdup (account_info[i].user_name);
776
u->real_name = g_strdup (account_info[i].real_name);
777
indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u);
780
users[2]->is_current_user = false;
781
indicator_session_users_changed (mock_users, users[2]->uid);
782
users[10]->is_current_user = true;
783
users[10]->is_logged_in = true;
784
indicator_session_users_changed (mock_users, users[10]->uid);
785
wait_for_menu_resync ();
786
ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos));
788
ASSERT_EQ (9, g_menu_model_get_n_items (switch_menu));
789
check_label ("Eleventh Doctor", switch_menu, 2);
790
check_label ("Fifth Doctor", switch_menu, 3);
791
check_label ("First Doctor", switch_menu, 4);
792
check_label ("Fourth Doctor", switch_menu, 5);
793
check_label ("Second Doctor", switch_menu, 6);
794
check_label ("Tenth Doctor", switch_menu, 7);
795
check_label ("Third Doctor", switch_menu, 8);
796
g_clear_object (&switch_menu);
798
// now switch to one of the doctors
799
g_action_group_activate_action (G_ACTION_GROUP(action_group),
801
g_variant_new_string("tbaker"));
802
wait_for_signal (mock_settings, "changed::last-command");
803
check_last_command_is ("switch-to-user::tbaker");