Merge lp:~aacid/unity-greeter/vala_testing_try into lp:unity-greeter

Proposed by Albert Astals Cid
Status: Merged
Merged at revision: 573
Proposed branch: lp:~aacid/unity-greeter/vala_testing_try
Merge into: lp:unity-greeter
Diff against target: 1624 lines (+1121/-86)
17 files modified
.bzrignore (+3/-0)
Makefile.am (+1/-1)
configure.ac (+1/-0)
po/POTFILES.skip (+5/-0)
src/background.vala (+12/-4)
src/greeter-list.vala (+14/-14)
src/main-window.vala (+1/-1)
src/menubar.vala (+1/-1)
src/session-list.vala (+1/-1)
src/unity-greeter.vala (+109/-37)
src/user-list.vala (+27/-27)
tests/Makefile.am (+63/-0)
tests/menubar.vala (+35/-0)
tests/test-list.vala (+18/-0)
tests/test-main-window.vala (+12/-0)
tests/test.vala (+690/-0)
tests/unity-greeter.vala (+128/-0)
To merge this branch: bzr merge lp:~aacid/unity-greeter/vala_testing_try
Reviewer Review Type Date Requested Status
Michael Terry (community) Approve
Review via email: mp+122242@code.launchpad.net

Description of the change

Some automated testing

Contains a refactoring to make the UnityGreeter a singleton so it can forward singletons from the Lightdm.Greeter

Needs a lightdm with https://code.launchpad.net/~aacid/lightdm/vala_enum_int merged in (or you can just edit that file in its installed location for quick testing)

To post a comment you must log in.
Revision history for this message
Michael Terry (mterry) wrote :

tests/Makefile.am:
noinst_PROGRAMS should be check_PROGRAMS (won't be built until user runs make check)

When running make check, I get:
** (./unity-greeter-test:11552): WARNING **: Couldn't connect to accessibility bus: Failed to connect to socket /tmp/dbus-qYpCYbTcHT: Connection refused
/bin/bash: line 5: 11552 Trace/breakpoint trap (core dumped) ${dir}$tst
FAIL: unity-greeter-test

Why "Posix.usleep (10000)" in process_events()?

"GLib.assert (list.num_entries() == 28)" in simple_navigation() seems brittle. Obviously we'll have to update it as we add new users, which isn't so bad. But is it expecting remote-login user to be there? In other tests, you have a function to wait for remote-login to appear. But at the end of this function, it assumes it is there by checking "*remote_directory*http://crazyurl.com".

Various test functions should probably use inject_key() to inject HOME, UP, DOWN, and END keys instead of calling do_scroll directly? I guess that's like an integration vs unit testing issue. Given the choice, I generally prefer integration.

Overall design comments:
So we're mocking out MenuBar and UnityGreeter. I suppose if we want to test those, we can add another executable with different mocks.

The whole thing seems a bit brittle to me. It's very reliant on current internals. And lots of timeouts and knowing that the Active user is first and such. I guess that's the problem with testing an app that wasn't well-designed for testing it, unlike a library that at least has an API barrier to test.

review: Needs Fixing
578. By Albert Astals Cid

Use check_ instead of noinst_ as suggested by mterry

Revision history for this message
Albert Astals Cid (aacid) wrote :

> tests/Makefile.am:
> noinst_PROGRAMS should be check_PROGRAMS (won't be built until user runs make
> check)

Done

> When running make check, I get:
> ** (./unity-greeter-test:11552): WARNING **: Couldn't connect to accessibility
> bus: Failed to connect to socket /tmp/dbus-qYpCYbTcHT: Connection refused
> /bin/bash: line 5: 11552 Trace/breakpoint trap (core dumped) ${dir}$tst
> FAIL: unity-greeter-test

Can't repro, are you using as a regular user or in some special setup?

>
> Why "Posix.usleep (10000)" in process_events()?

No need to burn your cpu, it doesn't really belong there but in all the while's that call process_events, i'll move it somewhere else so it's in the proper place.

> "GLib.assert (list.num_entries() == 28)" in simple_navigation() seems brittle.
> Obviously we'll have to update it as we add new users, which isn't so bad.
> But is it expecting remote-login user to be there?
No, it's not

> In other tests, you have a
> function to wait for remote-login to appear. But at the end of this function,
> it assumes it is there by checking "*remote_directory*http://crazyurl.com".

Yeah, it's because scrolling will take enough time for the 1s timeout we add for remote login to appear to have passed. I can add some comment explaining that if you prefer

> Various test functions should probably use inject_key() to inject HOME, UP,
> DOWN, and END keys instead of calling do_scroll directly? I guess that's like
> an integration vs unit testing issue. Given the choice, I generally prefer
> integration.

The thing is that i only use inject_key where it is really needed (i.e. in a place where it has to "overwrite" the selected text in the autocompleter). I will try to use inject_key

>
> Overall design comments:
> So we're mocking out MenuBar and UnityGreeter. I suppose if we want to test
> those, we can add another executable with different mocks.
Yep

> The whole thing seems a bit brittle to me. It's very reliant on current
> internals. And lots of timeouts and knowing that the Active user is first and
> such. I guess that's the problem with testing an app that wasn't well-
> designed for testing it, unlike a library that at least has an API barrier to
> test.
Yep, but the timeouts, active etc are not really "internals" but "test mode" internals, i.e. part of the test is in the test/ folder and the "data" of it is in the test_mode = true part of the code so that you can also test it manually. I guess i could refactor it a lot to make it look a bit nicer, not sure it's worth it though.

579. By Albert Astals Cid

Don't be time dependand with the 28 vs 29 depending if the remote login has appeared already or not

580. By Albert Astals Cid

remove the pop, doesn't do anything since the list doesn't want to be empty

581. By Albert Astals Cid

Move the usleeps to the whiles

582. By Albert Astals Cid

inject_key instead of calling the scroll function directly

583. By Albert Astals Cid

Use xvfb-run as suggested by mterry

584. By Albert Astals Cid

need this to make it a bit more robust

585. By Albert Astals Cid

Use our own gsettings

586. By Albert Astals Cid

also add dbus-launch

587. By Albert Astals Cid

Do not assert (while testing) if the backgrounds are not installed

Revision history for this message
Albert Astals Cid (aacid) wrote :

Ok, tested in a chroot and tests seem to be passing fine there too

Revision history for this message
Michael Terry (mterry) wrote :

Agreed, works in a chroot! Thanks. That will let us turn this on during package build.

Looks OK to me. One last (hopefully) question: I had earlier mentioned that the usleeps made me feel like things were a bit racy. You've now taken it out of the process_events function, but then sprinkled them around, usually right after a process_events call. Why are they needed? Are they races that we don't have control over and thus can't just fix directly?

Revision history for this message
Albert Astals Cid (aacid) wrote :

As said on the previous comment the usleeps are there so you don't burn your CPU, there's no need to do a huge busy loop waiting for something to trigger, you can sleep 10ms and check again.

If it makes you feel unconfortable and we don't mind our servers using more CPU than needed I can remove them.

Revision history for this message
Michael Terry (mterry) wrote :

But I guess I didn't understand then either. Before, we slept before processing all events. Now, we sleep after processing all events. In neither case would we be burning CPU without the sleep, right?

During a sleep, the events aren't being queued up or anything, since a sleep will stop the glib mainloop, eh? So if you mean that the test as a whole is CPU intensive, that doesn't bother me. It's the nature of tests to be doing things until they are done, not to optimize for low CPU usage.

Revision history for this message
Michael Terry (mterry) wrote :

OK, I got sorted by Albert on IRC.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-08-07 13:08:38 +0000
3+++ .bzrignore 2012-09-12 14:04:20 +0000
4@@ -20,6 +20,9 @@
5 src/*.c
6 src/unity_greeter_vala.stamp
7 src/unity-greeter
8+tests/*.c
9+tests/unity_greeter_test_vala.stamp
10+tests/unity-greeter-test
11
12 config.h
13 config.h.in
14
15=== modified file 'Makefile.am'
16--- Makefile.am 2012-01-10 09:31:10 +0000
17+++ Makefile.am 2012-09-12 14:04:20 +0000
18@@ -1,6 +1,6 @@
19 # -*- Mode: Automake; indent-tabs-mode: t; tab-width: 4 -*-
20
21-SUBDIRS = data po src
22+SUBDIRS = data po src tests
23
24 EXTRA_DIST = \
25 autogen.sh \
26
27=== modified file 'configure.ac'
28--- configure.ac 2012-09-04 13:45:23 +0000
29+++ configure.ac 2012-09-12 14:04:20 +0000
30@@ -48,5 +48,6 @@
31 data/Makefile
32 po/Makefile.in
33 src/Makefile
34+tests/Makefile
35 ])
36 AC_OUTPUT
37
38=== modified file 'po/POTFILES.skip'
39--- po/POTFILES.skip 2012-08-03 13:31:27 +0000
40+++ po/POTFILES.skip 2012-09-12 14:04:20 +0000
41@@ -19,4 +19,9 @@
42 src/unity-greeter.c
43 src/user-list.c
44 src/user-prompt-box.c
45+tests/greeter-list.c
46+tests/main-window.c
47+tests/prompt-box.c
48+tests/session-list.c
49+tests/user-list.c
50
51
52=== modified file 'src/background.vala'
53--- src/background.vala 2012-08-30 02:54:58 +0000
54+++ src/background.vala 2012-09-12 14:04:20 +0000
55@@ -122,10 +122,18 @@
56
57 for (var i = 0; i < widths.length; i++)
58 {
59- patterns[i] = create_pattern (images[i]);
60- if (i == 0)
61- pixbuf_average_value (images[i], out average_color);
62- images[i] = null;
63+ if (images[i] != null)
64+ {
65+ patterns[i] = create_pattern (images[i]);
66+ if (i == 0)
67+ pixbuf_average_value (images[i], out average_color);
68+ images[i] = null;
69+ }
70+ else
71+ {
72+ debug ("images[%d] was null for %s", i, filename);
73+ patterns[i] = null;
74+ }
75 }
76
77 loaded ();
78
79=== modified file 'src/greeter-list.vala'
80--- src/greeter-list.vala 2012-08-30 15:02:23 +0000
81+++ src/greeter-list.vala 2012-09-12 14:04:20 +0000
82@@ -176,7 +176,7 @@
83
84 public void cancel_authentication ()
85 {
86- UnityGreeter.greeter.cancel_authentication ();
87+ UnityGreeter.singleton.cancel_authentication ();
88 entry_selected (selected_entry.id);
89 }
90
91@@ -699,9 +699,9 @@
92
93 protected void connect_to_lightdm ()
94 {
95- UnityGreeter.greeter.show_message.connect (show_message_cb);
96- UnityGreeter.greeter.show_prompt.connect (show_prompt_cb);
97- UnityGreeter.greeter.authentication_complete.connect (authentication_complete_cb);
98+ UnityGreeter.singleton.show_message.connect (show_message_cb);
99+ UnityGreeter.singleton.show_prompt.connect (show_prompt_cb);
100+ UnityGreeter.singleton.authentication_complete.connect (authentication_complete_cb);
101 }
102
103 protected void show_message_cb (string text, LightDM.MessageType type)
104@@ -714,10 +714,10 @@
105 /* Notify the greeter on what user has been logged */
106 if (get_selected_id () == "*other" && manual_name == null)
107 {
108- if (UnityGreeter.test_mode)
109+ if (UnityGreeter.singleton.test_mode)
110 manual_name = test_username;
111 else
112- manual_name = UnityGreeter.greeter.authentication_user;
113+ manual_name = UnityGreeter.singleton.authentication_user();
114 }
115
116 prompted = true;
117@@ -743,10 +743,10 @@
118 return;
119
120 bool is_authenticated;
121- if (UnityGreeter.test_mode)
122+ if (UnityGreeter.singleton.test_mode)
123 is_authenticated = test_is_authenticated;
124 else
125- is_authenticated = UnityGreeter.greeter.is_authenticated;
126+ is_authenticated = UnityGreeter.singleton.is_authenticated();
127
128 if (is_authenticated)
129 {
130@@ -754,7 +754,7 @@
131 if (prompted)
132 {
133 login_complete ();
134- if (UnityGreeter.test_mode)
135+ if (UnityGreeter.singleton.test_mode)
136 start_session ();
137 else
138 {
139@@ -806,16 +806,16 @@
140
141 greeter_authenticating_user = get_selected_id ();
142
143- if (UnityGreeter.test_mode)
144+ if (UnityGreeter.singleton.test_mode)
145 test_start_authentication ();
146 else
147 {
148 if (get_selected_id () == "*other")
149- UnityGreeter.greeter.authenticate ();
150+ UnityGreeter.singleton.authenticate ();
151 else if (get_selected_id () == "*guest")
152- UnityGreeter.greeter.authenticate_as_guest ();
153+ UnityGreeter.singleton.authenticate_as_guest ();
154 else
155- UnityGreeter.greeter.authenticate (get_selected_id ());
156+ UnityGreeter.singleton.authenticate (get_selected_id ());
157 }
158 }
159
160@@ -834,7 +834,7 @@
161 background.draw_grid = false;
162 background.queue_draw ();
163
164- UnityGreeter.start_session (get_lightdm_session ());
165+ UnityGreeter.singleton.start_session (get_lightdm_session ());
166 }
167
168 public void login_complete ()
169
170=== modified file 'src/main-window.vala'
171--- src/main-window.vala 2012-08-30 14:37:46 +0000
172+++ src/main-window.vala 2012-09-12 14:04:20 +0000
173@@ -93,7 +93,7 @@
174
175 add_user_list ();
176
177- if (UnityGreeter.test_mode)
178+ if (UnityGreeter.singleton.test_mode)
179 {
180 /* Simulate an 800x600 monitor to the left of a 640x480 monitor */
181 monitors = new List<Monitor> ();
182
183=== modified file 'src/menubar.vala'
184--- src/menubar.vala 2012-09-04 14:10:33 +0000
185+++ src/menubar.vala 2012-09-12 14:04:20 +0000
186@@ -267,7 +267,7 @@
187 }
188 keyboard_label.label = desc;
189
190- if (UnityGreeter.test_mode)
191+ if (UnityGreeter.singleton.test_mode)
192 debug ("Setting layout to %s", layout.name);
193 else
194 LightDM.set_layout (layout);
195
196=== modified file 'src/session-list.vala'
197--- src/session-list.vala 2012-09-06 08:48:36 +0000
198+++ src/session-list.vala 2012-09-12 14:04:20 +0000
199@@ -33,7 +33,7 @@
200 {
201 label = _("Select desktop environment");
202
203- if (UnityGreeter.test_mode)
204+ if (UnityGreeter.singleton.test_mode)
205 {
206 add_session ("gnome", "GNOME");
207 add_session ("kde", "KDE");
208
209=== modified file 'src/unity-greeter.vala'
210--- src/unity-greeter.vala 2012-09-04 14:10:33 +0000
211+++ src/unity-greeter.vala 2012-09-12 14:04:20 +0000
212@@ -21,37 +21,42 @@
213
214 public class UnityGreeter
215 {
216- static bool show_version = false;
217- public static bool test_mode = false;
218- public static const OptionEntry[] options =
219- {
220- { "version", 'v', 0, OptionArg.NONE, ref show_version,
221- /* Help string for command line --version flag */
222- N_("Show release version"), null },
223- { "test-mode", 0, 0, OptionArg.NONE, ref test_mode,
224- /* Help string for command line --test-mode flag */
225- N_("Run in test mode"), null },
226- { null }
227- };
228-
229- private static Timer log_timer;
230-
231- private static string state_file;
232- private static KeyFile state;
233-
234- private static Cairo.XlibSurface background_surface;
235+ public static UnityGreeter singleton;
236+
237+ public signal void show_message (string text, LightDM.MessageType type);
238+ public signal void show_prompt (string text, LightDM.PromptType type);
239+ public signal void authentication_complete ();
240+
241+ public bool test_mode = false;
242+
243+ private string state_file;
244+ private KeyFile state;
245+
246+ private Cairo.XlibSurface background_surface;
247
248 private SettingsDaemon settings_daemon;
249
250- private static MainWindow main_window;
251+ private MainWindow main_window;
252
253- public static LightDM.Greeter greeter;
254+ private LightDM.Greeter greeter;
255
256 private Canberra.Context canberra_context;
257
258- public UnityGreeter ()
259+ private static Timer log_timer;
260+
261+ private UnityGreeter (bool test_mode_)
262 {
263+ singleton = this;
264+ test_mode = test_mode_;
265+
266+ /* Prepare to set the background */
267+ debug ("Creating background surface");
268+ background_surface = create_root_surface (Gdk.Screen.get_default ());
269+
270 greeter = new LightDM.Greeter ();
271+ greeter.show_message.connect ((text, type) => { show_message (text, type); });
272+ greeter.show_prompt.connect ((text, type) => { show_prompt (text, type); });
273+ greeter.authentication_complete.connect (() => { authentication_complete (); });
274 var connected = false;
275 try
276 {
277@@ -91,7 +96,7 @@
278 Gdk.threads_add_idle (ready_cb);
279 }
280
281- public static string? get_state (string key)
282+ public string? get_state (string key)
283 {
284 try
285 {
286@@ -103,7 +108,7 @@
287 }
288 }
289
290- public static void set_state (string key, string value)
291+ public void set_state (string key, string value)
292 {
293 state.set_value ("greeter", key, value);
294 var data = state.to_data ();
295@@ -117,12 +122,12 @@
296 }
297 }
298
299- public static void push_list (GreeterList widget)
300+ public void push_list (GreeterList widget)
301 {
302 main_window.push_list (widget);
303 }
304
305- public static void pop_list ()
306+ public void pop_list ()
307 {
308 main_window.pop_list ();
309 }
310@@ -144,12 +149,12 @@
311 return null;
312 }
313
314- public static void start_session (string? session)
315+ public void start_session (string? session)
316 {
317 /* Set the background */
318 refresh_background (Gdk.Screen.get_default (), background_surface);
319
320- if (UnityGreeter.test_mode)
321+ if (test_mode)
322 {
323 debug ("Successfully logged in! Quitting...");
324 Gtk.main_quit ();
325@@ -158,7 +163,7 @@
326 {
327 try
328 {
329- UnityGreeter.greeter.start_session_sync (session);
330+ greeter.start_session_sync (session);
331 }
332 catch (Error e)
333 {
334@@ -192,7 +197,67 @@
335 main_window.set_keyboard_state ();
336 }
337
338- private static Gdk.FilterReturn focus_upon_map (Gdk.XEvent gxevent, Gdk.Event event)
339+ public bool is_authenticated ()
340+ {
341+ return greeter.is_authenticated;
342+ }
343+
344+ public void authenticate (string? userid = null)
345+ {
346+ greeter.authenticate (userid);
347+ }
348+
349+ public void authenticate_as_guest ()
350+ {
351+ greeter.authenticate_as_guest ();
352+ }
353+
354+ public void authenticate_remote (string? session, string? userid)
355+ {
356+ UnityGreeter.singleton.greeter.authenticate_remote (session, userid);
357+ }
358+
359+ public void cancel_authentication ()
360+ {
361+ greeter.cancel_authentication ();
362+ }
363+
364+ public void respond (string response)
365+ {
366+ greeter.respond (response);
367+ }
368+
369+ public string authentication_user ()
370+ {
371+ return greeter.authentication_user;
372+ }
373+
374+ public string default_session_hint ()
375+ {
376+ return greeter.default_session_hint;
377+ }
378+
379+ public string select_user_hint ()
380+ {
381+ return greeter.select_user_hint;
382+ }
383+
384+ public bool show_manual_login_hint ()
385+ {
386+ return greeter.show_manual_login_hint;
387+ }
388+
389+ public bool hide_users_hint ()
390+ {
391+ return greeter.hide_users_hint;
392+ }
393+
394+ public bool has_guest_account_hint ()
395+ {
396+ return greeter.has_guest_account_hint;
397+ }
398+
399+ private Gdk.FilterReturn focus_upon_map (Gdk.XEvent gxevent, Gdk.Event event)
400 {
401 var xevent = (X.Event*)gxevent;
402 if (xevent.type == X.EventType.MapNotify)
403@@ -344,9 +409,16 @@
404 debug ("Setting cursor");
405 Gdk.get_default_root_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.LEFT_PTR));
406
407- /* Prepare to set the background */
408- debug ("Creating background surface");
409- background_surface = create_root_surface (Gdk.Screen.get_default ());
410+ bool do_show_version = false;
411+ bool do_test_mode = false;
412+ OptionEntry versionOption = { "version", 'v', 0, OptionArg.NONE, ref do_show_version,
413+ /* Help string for command line --version flag */
414+ N_("Show release version"), null };
415+ OptionEntry testOption = { "test-mode", 0, 0, OptionArg.NONE, ref do_test_mode,
416+ /* Help string for command line --test-mode flag */
417+ N_("Run in test mode"), null };
418+ OptionEntry nullOption = { null };
419+ OptionEntry[] options = { versionOption, testOption, nullOption };
420
421 debug ("Loading command line options");
422 var c = new OptionContext (/* Arguments and description for --help text */
423@@ -365,17 +437,17 @@
424 stderr.printf ("\n");
425 return Posix.EXIT_FAILURE;
426 }
427- if (show_version)
428+ if (do_show_version)
429 {
430 /* Note, not translated so can be easily parsed */
431 stderr.printf ("unity-greeter %s\n", Config.VERSION);
432 return Posix.EXIT_SUCCESS;
433 }
434
435- if (test_mode)
436+ if (do_test_mode)
437 debug ("Running in test mode");
438
439- if (!test_mode)
440+ if (!do_test_mode)
441 {
442 /* Make nm-applet hide items the user does not have permissions to interact with */
443 Environment.set_variable ("NM_APPLET_HIDE_POLICY_ITEMS", "1", true);
444@@ -415,7 +487,7 @@
445 settings.set ("gtk-xft-rgba", value, null);
446
447 debug ("Creating Unity Greeter");
448- var greeter = new UnityGreeter ();
449+ var greeter = new UnityGreeter (do_test_mode);
450
451 debug ("Showing greeter");
452 greeter.show ();
453
454=== modified file 'src/user-list.vala'
455--- src/user-list.vala 2012-09-04 14:10:33 +0000
456+++ src/user-list.vala 2012-09-12 14:04:20 +0000
457@@ -129,7 +129,7 @@
458
459 connect_to_lightdm ();
460
461- if (!UnityGreeter.test_mode && UGSettings.get_boolean (UGSettings.KEY_ENABLE_REMOTE_LOGIN))
462+ if (!UnityGreeter.singleton.test_mode && UGSettings.get_boolean (UGSettings.KEY_ENABLE_REMOTE_LOGIN))
463 remote_login_service_watch = Bus.watch_name (BusType.SESSION,
464 "com.canonical.RemoteLogin",
465 BusNameWatcherFlags.AUTO_START,
466@@ -372,7 +372,7 @@
467 try
468 {
469 var url = url_from_remote_loding_server_list_name (selected_entry.id);
470- if (UnityGreeter.test_mode)
471+ if (UnityGreeter.singleton.test_mode)
472 {
473 if (password_field.text == "password")
474 {
475@@ -445,7 +445,7 @@
476 sensitive = false;
477 will_clear = true;
478 greeter_authenticating_user = selected_entry.id;
479- if (UnityGreeter.test_mode)
480+ if (UnityGreeter.singleton.test_mode)
481 {
482 Gtk.Entry field = current_remote_fields.get ("password") as Gtk.Entry;
483 test_is_authenticated = field.text == "password";
484@@ -456,7 +456,7 @@
485 }
486 else
487 {
488- UnityGreeter.greeter.authenticate_remote (get_lightdm_session (), null);
489+ UnityGreeter.singleton.authenticate_remote (get_lightdm_session (), null);
490 remote_login_service.set_last_used_server.begin (currently_browsing_server_url, url_from_remote_loding_server_list_name (selected_entry.id));
491 }
492 }
493@@ -487,7 +487,7 @@
494 if (is_supported_remote_session (config_session))
495 {
496 greeter_authenticating_user = selected_entry.id;
497- UnityGreeter.greeter.authenticate_remote (config_session, null);
498+ UnityGreeter.singleton.authenticate_remote (config_session, null);
499 }
500 }
501 dialog.destroy ();
502@@ -546,7 +546,7 @@
503
504 private void entry_selected_cb (string? username)
505 {
506- UnityGreeter.set_state ("last-user", username);
507+ UnityGreeter.singleton.set_state ("last-user", username);
508 if (selected_entry is UserPromptBox)
509 session = (selected_entry as UserPromptBox).session;
510 else
511@@ -680,7 +680,7 @@
512 string[] email_domains;
513 try
514 {
515- if (UnityGreeter.test_mode)
516+ if (UnityGreeter.singleton.test_mode)
517 email_domains = { "canonical.com", "ubuntu.org", "candy.com", "urban.net" };
518 else
519 yield remote_login_service.get_cached_domains_for_server (url, out email_domains);
520@@ -791,10 +791,10 @@
521
522 foreach (var response in responses)
523 {
524- if (UnityGreeter.test_mode)
525+ if (UnityGreeter.singleton.test_mode)
526 test_respond (response);
527 else
528- UnityGreeter.greeter.respond (response);
529+ UnityGreeter.singleton.respond (response);
530 }
531 }
532
533@@ -803,10 +803,10 @@
534 debug ("Start session for %s", selected_entry.id);
535
536 var is_authenticated = false;
537- if (UnityGreeter.test_mode)
538+ if (UnityGreeter.singleton.test_mode)
539 is_authenticated = test_is_authenticated;
540 else
541- is_authenticated = UnityGreeter.greeter.is_authenticated;
542+ is_authenticated = UnityGreeter.singleton.is_authenticated();
543
544 /* Finish authentication (again) or restart it */
545 if (is_authenticated)
546@@ -822,13 +822,13 @@
547 {
548 var session_chooser = new SessionList (background, menubar, session, default_session);
549 session_chooser.session_clicked.connect (session_clicked_cb);
550- UnityGreeter.push_list (session_chooser);
551+ UnityGreeter.singleton.push_list (session_chooser);
552 }
553
554 private void session_clicked_cb (string session)
555 {
556 this.session = session;
557- UnityGreeter.pop_list ();
558+ UnityGreeter.singleton.pop_list ();
559 }
560
561 private Gdk.Pixbuf? get_badge ()
562@@ -851,7 +851,7 @@
563
564 private bool is_supported_remote_session (string session_internal_name)
565 {
566- if (UnityGreeter.test_mode)
567+ if (UnityGreeter.singleton.test_mode)
568 return session_internal_name == "rdp";
569
570 var found = false;
571@@ -893,13 +893,13 @@
572
573 private void fill_list ()
574 {
575- if (UnityGreeter.test_mode)
576+ if (UnityGreeter.singleton.test_mode)
577 test_fill_list ();
578 else
579 {
580- default_session = UnityGreeter.greeter.default_session_hint;
581- always_show_manual = UnityGreeter.greeter.show_manual_login_hint;
582- if (!UnityGreeter.greeter.hide_users_hint)
583+ default_session = UnityGreeter.singleton.default_session_hint ();
584+ always_show_manual = UnityGreeter.singleton.show_manual_login_hint ();
585+ if (!UnityGreeter.singleton.hide_users_hint ())
586 {
587 var users = LightDM.UserList.get_instance ();
588 users.user_added.connect (user_added_cb);
589@@ -909,15 +909,15 @@
590 user_added_cb (user);
591 }
592
593- if (UnityGreeter.greeter.has_guest_account_hint)
594+ if (UnityGreeter.singleton.has_guest_account_hint ())
595 {
596 debug ("Adding guest account entry");
597 offer_guest = true;
598 }
599
600- var last_user = UnityGreeter.get_state ("last-user");
601- if (UnityGreeter.greeter.select_user_hint != null)
602- set_active_entry (UnityGreeter.greeter.select_user_hint);
603+ var last_user = UnityGreeter.singleton.get_state ("last-user");
604+ if (UnityGreeter.singleton.select_user_hint () != null)
605+ set_active_entry (UnityGreeter.singleton.select_user_hint ());
606 else if (last_user != null)
607 set_active_entry (last_user);
608 }
609@@ -956,24 +956,24 @@
610 {
611 Gtk.Entry field = current_remote_fields.get ("username") as Gtk.Entry;
612 var answer = field != null ? field.text : "";
613- UnityGreeter.greeter.respond (answer);
614+ UnityGreeter.singleton.respond (answer);
615 }
616 else if (text == "password:")
617 {
618 Gtk.Entry field = current_remote_fields.get ("password") as Gtk.Entry;
619 var answer = field != null ? field.text : "";
620- UnityGreeter.greeter.respond (answer);
621+ UnityGreeter.singleton.respond (answer);
622 }
623 else if (text == "remote host:")
624 {
625 var answer = url_from_remote_loding_server_list_name (selected_entry.id);
626- UnityGreeter.greeter.respond (answer);
627+ UnityGreeter.singleton.respond (answer);
628 }
629 else if (text == "domain:")
630 {
631 Gtk.Entry field = current_remote_fields.get ("domain") as Gtk.Entry;
632 var answer = field != null ? field.text : "";
633- UnityGreeter.greeter.respond (answer);
634+ UnityGreeter.singleton.respond (answer);
635 }
636 }
637 else
638@@ -1074,7 +1074,7 @@
639 return false;
640 });
641
642- var last_user = UnityGreeter.get_state ("last-user");
643+ var last_user = UnityGreeter.singleton.get_state ("last-user");
644 if (last_user != null)
645 set_active_entry (last_user);
646
647
648=== added directory 'tests'
649=== added file 'tests/Makefile.am'
650--- tests/Makefile.am 1970-01-01 00:00:00 +0000
651+++ tests/Makefile.am 2012-09-12 14:04:20 +0000
652@@ -0,0 +1,63 @@
653+# -*- Mode: Automake; indent-tabs-mode: t; tab-width: 4 -*-
654+
655+check_PROGRAMS = unity-greeter-test
656+
657+check: unity-greeter-test
658+ xvfb-run dbus-launch ./unity-greeter-test
659+
660+unity_greeter_test_SOURCES = \
661+ test.vala \
662+ test-list.vala \
663+ test-main-window.vala \
664+ menubar.vala \
665+ unity-greeter.vala \
666+ ../src/user-list.vala \
667+ ../src/greeter-list.vala \
668+ ../src/remote-login-service.vala \
669+ ../src/background.vala \
670+ ../src/email-autocompleter.vala \
671+ ../src/config.vapi \
672+ ../src/fixes.vapi \
673+ ../src/animate-timer.vala \
674+ ../src/indicator.vapi \
675+ ../src/fadable.vala \
676+ ../src/fadable-box.vala \
677+ ../src/dash-box.vala \
678+ ../src/user-prompt-box.vala \
679+ ../src/fading-label.vala \
680+ ../src/cached-image.vala \
681+ ../src/dash-entry.vala \
682+ ../src/dash-button.vala \
683+ ../src/prompt-box.vala \
684+ ../src/session-list.vala \
685+ ../src/main-window.vala \
686+ ../src/list-stack.vala \
687+ ../src/settings.vala
688+
689+
690+unity_greeter_test_CFLAGS = \
691+ $(UNITY_GREETER_CFLAGS) \
692+ $(WARN_CFLAGS) \
693+ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
694+ -DLOCALEDIR=\""$(localedir)"\" \
695+ -DVERSION=\"$(VERSION)\" \
696+ -DCONFIG_FILE=\""$(sysconfdir)/lightdm/unity-greeter.conf"\" \
697+ -DPKGDATADIR=\""$(pkgdatadir)"\" \
698+ -DINDICATORDIR=\""$(INDICATORDIR)"\"
699+
700+unity_greeter_test_VALAFLAGS = \
701+ --pkg posix \
702+ --pkg gtk+-3.0 \
703+ --pkg gdk-x11-3.0 \
704+ --pkg gio-unix-2.0 \
705+ --pkg x11 \
706+ --pkg liblightdm-gobject-1 \
707+ --pkg libcanberra \
708+ --pkg gio-2.0 \
709+ --target-glib 2.32
710+
711+unity_greeter_test_LDADD = \
712+ $(UNITY_GREETER_LIBS)
713+
714+DISTCLEANFILES = \
715+ Makefile.in
716
717=== added file 'tests/menubar.vala'
718--- tests/menubar.vala 1970-01-01 00:00:00 +0000
719+++ tests/menubar.vala 2012-09-12 14:04:20 +0000
720@@ -0,0 +1,35 @@
721+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
722+ *
723+ * Copyright (C) 2012 Canonical Ltd
724+ *
725+ * This program is free software: you can redistribute it and/or modify
726+ * it under the terms of the GNU General Public License version 3 as
727+ * published by the Free Software Foundation.
728+ *
729+ * This program is distributed in the hope that it will be useful,
730+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
731+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
732+ * GNU General Public License for more details.
733+ *
734+ * You should have received a copy of the GNU General Public License
735+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
736+ *
737+ */
738+
739+public class MenuBar : Gtk.MenuBar
740+{
741+ public static const int HEIGHT = 32;
742+ public bool high_contrast { get; private set; default = false; }
743+
744+ public MenuBar (Background bg, Gtk.AccelGroup ag)
745+ {
746+ }
747+
748+ public void set_layouts (List <LightDM.Layout> layouts)
749+ {
750+ }
751+
752+ public void set_keyboard_state ()
753+ {
754+ }
755+}
756
757=== added file 'tests/test-list.vala'
758--- tests/test-list.vala 1970-01-01 00:00:00 +0000
759+++ tests/test-list.vala 2012-09-12 14:04:20 +0000
760@@ -0,0 +1,18 @@
761+
762+public class TestList : UserList
763+{
764+ public TestList (Background bg, MenuBar mb)
765+ {
766+ Object (background: bg, menubar: mb);
767+ }
768+
769+ public uint num_entries ()
770+ {
771+ return entries.length();
772+ }
773+
774+ public bool is_scrolling ()
775+ {
776+ return mode == Mode.SCROLLING;
777+ }
778+}
779\ No newline at end of file
780
781=== added file 'tests/test-main-window.vala'
782--- tests/test-main-window.vala 1970-01-01 00:00:00 +0000
783+++ tests/test-main-window.vala 2012-09-12 14:04:20 +0000
784@@ -0,0 +1,12 @@
785+
786+public class TestMainWindow : MainWindow
787+{
788+ public TestMainWindow ()
789+ {
790+ }
791+
792+ public Background get_background ()
793+ {
794+ return get_child() as Background;
795+ }
796+}
797
798=== added file 'tests/test.vala'
799--- tests/test.vala 1970-01-01 00:00:00 +0000
800+++ tests/test.vala 2012-09-12 14:04:20 +0000
801@@ -0,0 +1,690 @@
802+
803+public class Test
804+{
805+ private static MainWindow setup ()
806+ {
807+ TestMainWindow main_window = new TestMainWindow ();
808+ var list = new TestList (main_window.get_background (), main_window.menubar);
809+ main_window.push_list (list);
810+ main_window.show_all();
811+ // Make sure we are really shown
812+ process_events ();
813+
814+ return main_window;
815+ }
816+
817+ private static void process_events ()
818+ {
819+ while (Gtk.events_pending ())
820+ Gtk.main_iteration ();
821+ }
822+
823+ private static void wait_for_scrolling_end (TestList list)
824+ {
825+ while (list.is_scrolling ())
826+ {
827+ process_events ();
828+ Posix.usleep (10000);
829+ }
830+ }
831+
832+ // BEGIN This group of functions asume email/password for remote directory servers
833+ private static DashEntry remote_directory_entry_email_field (TestList list)
834+ {
835+ var fixed = list.selected_entry.get_child() as Gtk.Fixed;
836+ var grid = fixed.get_children().nth_data(1) as Gtk.Grid;
837+ return grid.get_child_at(1, 1) as DashEntry;
838+ }
839+
840+ private static DashEntry remote_directory_entry_password_field (TestList list)
841+ {
842+ var fixed = list.selected_entry.get_child() as Gtk.Fixed;
843+ var grid = fixed.get_children().nth_data(1) as Gtk.Grid;
844+ return grid.get_child_at(1, 2) as DashEntry;
845+ }
846+ // END This group of functions asume email/password for remote directory servers
847+
848+ // BEGIN This group of functions asume domain/username/password for remote login servers
849+ private static DashEntry remote_login_entry_domain_field (TestList list)
850+ {
851+ var fixed = list.selected_entry.get_child() as Gtk.Fixed;
852+ var grid = fixed.get_children().nth_data(1) as Gtk.Grid;
853+ return grid.get_child_at(1, 1) as DashEntry;
854+ }
855+
856+ private static DashEntry remote_login_entry_username_field (TestList list)
857+ {
858+ var fixed = list.selected_entry.get_child() as Gtk.Fixed;
859+ var grid = fixed.get_children().nth_data(1) as Gtk.Grid;
860+ return grid.get_child_at(1, 2) as DashEntry;
861+ }
862+
863+ private static DashEntry remote_login_entry_password_field (TestList list)
864+ {
865+ var fixed = list.selected_entry.get_child() as Gtk.Fixed;
866+ var grid = fixed.get_children().nth_data(1) as Gtk.Grid;
867+ return grid.get_child_at(1, 3) as DashEntry;
868+ }
869+ // BEGIN This group of functions asume domain/username/password for remote login servers
870+
871+ private static void do_scroll (TestList list, GreeterList.ScrollTarget direction)
872+ {
873+ process_events ();
874+ switch (direction)
875+ {
876+ case GreeterList.ScrollTarget.START:
877+ inject_key (list, Gdk.Key.Page_Up);
878+ break;
879+ case GreeterList.ScrollTarget.END:
880+ inject_key (list, Gdk.Key.Page_Down);
881+ break;
882+ case GreeterList.ScrollTarget.UP:
883+ inject_key (list, Gdk.Key.Up);
884+ break;
885+ case GreeterList.ScrollTarget.DOWN:
886+ inject_key (list, Gdk.Key.Down);
887+ break;
888+ }
889+ wait_for_scrolling_end (list);
890+ }
891+
892+ private static void scroll_to_remote_login (TestList list)
893+ {
894+ do_scroll (list, GreeterList.ScrollTarget.END);
895+ while (list.selected_entry.id == "*guest")
896+ {
897+ do_scroll (list, GreeterList.ScrollTarget.END);
898+ process_events ();
899+ Posix.usleep (10000);
900+ }
901+ }
902+
903+ private static void inject_key (Gtk.Widget w, int keyval)
904+ {
905+ // Make sure everything is flushed
906+ process_events ();
907+
908+ Gdk.KeymapKey[] keys;
909+
910+ bool success = Gdk.Keymap.get_default ().get_entries_for_keyval (keyval, out keys);
911+ GLib.assert (success);
912+ Gdk.Event event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
913+ event.key.window = w.get_parent_window ();
914+ event.key.hardware_keycode = (int16)keys[0].keycode;
915+ event.key.keyval = keyval;
916+ event.set_device(Gdk.Display.get_default ().get_device_manager ().get_client_pointer ());
917+ event.key.time = Gdk.CURRENT_TIME;
918+
919+ Gtk.main_do_event (event);
920+ }
921+
922+ private static void wait_for_focus (Gtk.Widget w)
923+ {
924+ while (!w.has_focus)
925+ {
926+ process_events ();
927+ Posix.usleep (10000);
928+ }
929+ }
930+
931+ public static void simple_navigation ()
932+ {
933+ MainWindow mw = setup ();
934+ TestList list = mw.stack.top () as TestList;
935+
936+ // Wait until remote login appears
937+ scroll_to_remote_login (list);
938+
939+ GLib.assert (list.num_entries() == 29);
940+
941+ // Make sure we are at the beginning of the list
942+ do_scroll (list, GreeterList.ScrollTarget.START);
943+ GLib.assert (list.selected_entry.id == "active");
944+
945+ // Scrolling up does nothing
946+ do_scroll (list, GreeterList.ScrollTarget.UP);
947+ GLib.assert (list.selected_entry.id == "active");
948+
949+ // Scrolling down works
950+ do_scroll (list, GreeterList.ScrollTarget.DOWN);
951+ GLib.assert (list.selected_entry.id == "auth-error");
952+
953+ // Remote Login is at the end;
954+ do_scroll (list, GreeterList.ScrollTarget.END);
955+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
956+
957+ mw.hide ();
958+ }
959+
960+ public static void remote_login ()
961+ {
962+ MainWindow mw = setup ();
963+ TestList list = mw.stack.top () as TestList;
964+
965+ // Wait until remote login appears
966+ scroll_to_remote_login (list);
967+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
968+ GLib.assert (!list.selected_entry.has_errors);
969+
970+ // If we answer without filling in any field -> error
971+ list.selected_entry.respond ({});
972+ GLib.assert (list.selected_entry.has_errors);
973+
974+ // Go to first and back to last to clear the error
975+ do_scroll (list, GreeterList.ScrollTarget.START);
976+ do_scroll (list, GreeterList.ScrollTarget.END);
977+ GLib.assert (!list.selected_entry.has_errors);
978+
979+ // Fill in a valid email and password
980+ // Check there is no error and we moved to the last logged in server
981+ var email = remote_directory_entry_email_field (list);
982+ var pwd = remote_directory_entry_password_field (list);
983+ email.text = "a@canonical.com";
984+ pwd.text = "password";
985+ list.selected_entry.respond ({});
986+ GLib.assert (!list.selected_entry.has_errors);
987+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
988+ wait_for_scrolling_end (list);
989+
990+ // Go back to the remote_directory entry and write the same password but an invalid email
991+ // Check there is error and we did not move anywhere
992+ while (!list.selected_entry.id.has_prefix("*remote_directory*http://crazyurl.com"))
993+ do_scroll (list, GreeterList.ScrollTarget.UP);
994+ email = remote_directory_entry_email_field (list);
995+ pwd = remote_directory_entry_password_field (list);
996+ email.text = "a @ foobar";
997+ pwd.text = "password";
998+ list.selected_entry.respond ({});
999+ GLib.assert (list.selected_entry.has_errors);
1000+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1001+
1002+ mw.hide ();
1003+ }
1004+
1005+ public static void remote_login_servers_updated_signal ()
1006+ {
1007+ MainWindow mw = setup ();
1008+ TestList list = mw.stack.top () as TestList;
1009+
1010+ // Wait until remote login appears
1011+ scroll_to_remote_login (list);
1012+
1013+ var email = remote_directory_entry_email_field (list);
1014+ var pwd = remote_directory_entry_password_field (list);
1015+ email.text = "a@canonical.com";
1016+ pwd.text = "delay1";
1017+ list.selected_entry.respond ({});
1018+ GLib.assert (!list.selected_entry.has_errors);
1019+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1020+
1021+ bool done = false;
1022+ // The delay1 code triggers at 5 seconds
1023+ Timeout.add (5250, () =>
1024+ {
1025+ // If the directory server where were browsing disappears the login servers are removed too
1026+ // and we get moved to the new directory server
1027+ wait_for_scrolling_end (list);
1028+ GLib.assert (list.selected_entry.id == "*remote_directory*http://internalcompayserver.com");
1029+ done = true;
1030+ return false;
1031+ }
1032+ );
1033+
1034+ while (!done)
1035+ {
1036+ process_events ();
1037+ Posix.usleep (10000);
1038+ }
1039+
1040+ mw.hide ();
1041+ }
1042+
1043+ public static void remote_login_servers_updated_signal_focus_not_in_remote_server ()
1044+ {
1045+ MainWindow mw = setup ();
1046+ TestList list = mw.stack.top () as TestList;
1047+
1048+ // Wait until remote login appears
1049+ scroll_to_remote_login (list);
1050+
1051+ var email = remote_directory_entry_email_field (list);
1052+ var pwd = remote_directory_entry_password_field (list);
1053+ email.text = "a@canonical.com";
1054+ pwd.text = "delay1";
1055+ list.selected_entry.respond ({});
1056+ GLib.assert (!list.selected_entry.has_errors);
1057+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1058+ wait_for_scrolling_end (list);
1059+
1060+ while (list.selected_entry.id.has_prefix("*remote_"))
1061+ {
1062+ do_scroll (list, GreeterList.ScrollTarget.UP);
1063+ }
1064+ string nonRemoteEntry = list.selected_entry.id;
1065+
1066+ bool done = false;
1067+ // The delay1 code triggers at 5 seconds
1068+ Timeout.add (5250, () =>
1069+ {
1070+ // If we were not in a remote entry we are not moved even if the directory servers change
1071+ // Moving down we find the new directory server
1072+ GLib.assert (list.selected_entry.id == nonRemoteEntry);
1073+ do_scroll (list, GreeterList.ScrollTarget.DOWN);
1074+ GLib.assert (list.selected_entry.id == "*remote_directory*http://internalcompayserver.com");
1075+ done = true;
1076+ return false;
1077+ }
1078+ );
1079+
1080+ while (!done)
1081+ {
1082+ process_events ();
1083+ Posix.usleep (10000);
1084+ }
1085+
1086+ mw.hide ();
1087+ }
1088+
1089+ public static void remote_login_login_servers_updated_signal ()
1090+ {
1091+ MainWindow mw = setup ();
1092+ TestList list = mw.stack.top () as TestList;
1093+
1094+ // Wait until remote login appears
1095+ scroll_to_remote_login (list);
1096+
1097+ var email = remote_directory_entry_email_field (list);
1098+ var pwd = remote_directory_entry_password_field (list);
1099+ email.text = "a@canonical.com";
1100+ pwd.text = "delay2";
1101+ list.selected_entry.respond ({});
1102+ GLib.assert (!list.selected_entry.has_errors);
1103+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1104+
1105+ bool done = false;
1106+ // The delay2 code triggers at 5 seconds
1107+ Timeout.add (5250, () =>
1108+ {
1109+ // If the login server we were disappears we get moved to a different one
1110+ wait_for_scrolling_end (list);
1111+ GLib.assert (list.selected_entry.id == "*remote_login*http://megacoolrdpserver.com");
1112+ done = true;
1113+ return false;
1114+ }
1115+ );
1116+
1117+ while (!done)
1118+ {
1119+ process_events ();
1120+ Posix.usleep (10000);
1121+ }
1122+
1123+ mw.hide ();
1124+ }
1125+
1126+ public static void remote_login_login_servers_updated_signal_focus_not_in_removed_server ()
1127+ {
1128+ MainWindow mw = setup ();
1129+ TestList list = mw.stack.top () as TestList;
1130+
1131+ // Wait until remote login appears
1132+ scroll_to_remote_login (list);
1133+
1134+ var email = remote_directory_entry_email_field (list);
1135+ var pwd = remote_directory_entry_password_field (list);
1136+ email.text = "a@canonical.com";
1137+ pwd.text = "delay2";
1138+ list.selected_entry.respond ({});
1139+ GLib.assert (!list.selected_entry.has_errors);
1140+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1141+
1142+ // Move to a server that won't be removed
1143+ while (list.selected_entry.id != "*remote_login*http://coolrdpserver.com")
1144+ do_scroll (list, GreeterList.ScrollTarget.UP);
1145+
1146+ bool done = false;
1147+ // The delay2 code triggers at 5 seconds
1148+ Timeout.add (5250, () =>
1149+ {
1150+ // If the login server we were did not disappear we are still in the same one
1151+ wait_for_scrolling_end (list);
1152+ GLib.assert (list.selected_entry.id == "*remote_login*http://coolrdpserver.com");
1153+ done = true;
1154+ return false;
1155+ }
1156+ );
1157+
1158+ while (!done)
1159+ {
1160+ process_events ();
1161+ Posix.usleep (10000);
1162+ }
1163+
1164+ mw.hide ();
1165+ }
1166+
1167+ public static void remote_login_remote_login_changed_signal ()
1168+ {
1169+ MainWindow mw = setup ();
1170+ TestList list = mw.stack.top () as TestList;
1171+
1172+ // Wait until remote login appears
1173+ scroll_to_remote_login (list);
1174+
1175+ var email = remote_directory_entry_email_field (list);
1176+ var pwd = remote_directory_entry_password_field (list);
1177+ email.text = "a@canonical.com";
1178+ pwd.text = "delay3";
1179+ list.selected_entry.respond ({});
1180+ GLib.assert (!list.selected_entry.has_errors);
1181+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1182+
1183+ bool done = false;
1184+ // The delay3 code triggers at 5 seconds
1185+ Timeout.add (5250, () =>
1186+ {
1187+ // If the remote login details change while on one of its servers the login servers are removed
1188+ // and we get moved to the directory server
1189+ wait_for_scrolling_end (list);
1190+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1191+
1192+ do_scroll (list, GreeterList.ScrollTarget.DOWN); // There are no server to log in
1193+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1194+
1195+ done = true;
1196+ return false;
1197+ }
1198+ );
1199+
1200+ while (!done)
1201+ {
1202+ process_events ();
1203+ Posix.usleep (10000);
1204+ }
1205+
1206+ mw.hide ();
1207+ }
1208+
1209+ public static void remote_login_remote_login_changed_signalfocus_not_in_changed_server ()
1210+ {
1211+ MainWindow mw = setup ();
1212+ TestList list = mw.stack.top () as TestList;
1213+
1214+ // Wait until remote login appears
1215+ scroll_to_remote_login (list);
1216+
1217+ var email = remote_directory_entry_email_field (list);
1218+ var pwd = remote_directory_entry_password_field (list);
1219+ email.text = "a@canonical.com";
1220+ pwd.text = "delay3";
1221+ list.selected_entry.respond ({});
1222+ GLib.assert (!list.selected_entry.has_errors);
1223+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1224+ wait_for_scrolling_end (list);
1225+
1226+ while (list.selected_entry.id.has_prefix("*remote_"))
1227+ {
1228+ do_scroll (list, GreeterList.ScrollTarget.UP);
1229+ }
1230+ string nonRemoteEntry = list.selected_entry.id;
1231+
1232+ bool done = false;
1233+ // The delay3 code triggers at 5 seconds
1234+ Timeout.add (5250, () =>
1235+ {
1236+ // If we were not in a remote entry we are not moved when we are asked to reauthenticate
1237+ // What happens is that the login servers of that directory server get removed
1238+ // Moving down we find the new directory server
1239+ GLib.assert (list.selected_entry.id == nonRemoteEntry);
1240+ do_scroll (list, GreeterList.ScrollTarget.DOWN);
1241+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1242+
1243+ do_scroll (list, GreeterList.ScrollTarget.DOWN); // There are no server to log in
1244+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1245+ done = true;
1246+ return false;
1247+ }
1248+ );
1249+
1250+ while (!done)
1251+ {
1252+ process_events ();
1253+ Posix.usleep (10000);
1254+ }
1255+
1256+ mw.hide ();
1257+ }
1258+
1259+ public static void remote_login_authentication ()
1260+ {
1261+ MainWindow mw = setup ();
1262+ TestList list = mw.stack.top () as TestList;
1263+
1264+ // Wait until remote login appears
1265+ scroll_to_remote_login (list);
1266+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1267+ GLib.assert (!list.selected_entry.has_errors);
1268+
1269+ // Fill in a valid email and password
1270+ // Check there is no error and we moved to the last logged in server
1271+ var email = remote_directory_entry_email_field (list);
1272+ var pwd = remote_directory_entry_password_field (list);
1273+ email.text = "a@canonical.com";
1274+ pwd.text = "password";
1275+ list.selected_entry.respond ({});
1276+ GLib.assert (!list.selected_entry.has_errors);
1277+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1278+ wait_for_scrolling_end (list);
1279+
1280+ UnityGreeter.singleton.session_started = false;
1281+ pwd = remote_login_entry_password_field (list);
1282+ pwd.text = "password";
1283+ list.selected_entry.respond ({});
1284+ GLib.assert (UnityGreeter.singleton.session_started);
1285+
1286+ mw.hide ();
1287+ }
1288+
1289+ public static void remote_login_cancel_authentication ()
1290+ {
1291+ MainWindow mw = setup ();
1292+ TestList list = mw.stack.top () as TestList;
1293+
1294+ // Wait until remote login appears
1295+ scroll_to_remote_login (list);
1296+ GLib.assert (list.selected_entry.id == "*remote_directory*http://crazyurl.com");
1297+ GLib.assert (!list.selected_entry.has_errors);
1298+
1299+ // Fill in a valid email and password
1300+ // Check there is no error and we moved to the last logged in server
1301+ var email = remote_directory_entry_email_field (list);
1302+ var pwd = remote_directory_entry_password_field (list);
1303+ email.text = "a@canonical.com";
1304+ pwd.text = "password";
1305+ list.selected_entry.respond ({});
1306+ GLib.assert (!list.selected_entry.has_errors);
1307+ GLib.assert (list.selected_entry.id == "*remote_login*http://rdpdefaultusername2.com");
1308+ wait_for_scrolling_end (list);
1309+
1310+ UnityGreeter.singleton.session_started = false;
1311+ pwd = remote_login_entry_password_field (list);
1312+ pwd.text = "delay";
1313+ pwd.activate ();
1314+ GLib.assert (!list.sensitive); // We are not sensitive because we are waiting for servers answer
1315+ GLib.assert (pwd.did_respond); // We are showing the spinner
1316+ list.cancel_authentication ();
1317+ pwd = remote_login_entry_password_field (list);
1318+ GLib.assert (list.sensitive); // We are sensitive again because we cancelled the login
1319+ GLib.assert (!pwd.did_respond); // We are not showing the spinner anymore
1320+
1321+ mw.hide ();
1322+ }
1323+
1324+ public static void email_autocomplete ()
1325+ {
1326+ MainWindow mw = setup ();
1327+ TestList list = mw.stack.top () as TestList;
1328+
1329+ // Wait until remote login appears
1330+ scroll_to_remote_login (list);
1331+
1332+ var email = remote_directory_entry_email_field (list);
1333+
1334+ wait_for_focus (email);
1335+
1336+ GLib.assert (email.text.length == 0);
1337+
1338+ inject_key(email, Gdk.Key.a);
1339+ GLib.assert (email.text == "a");
1340+
1341+ inject_key(email, Gdk.Key.at);
1342+ GLib.assert (email.text == "a@canonical.com");
1343+
1344+ inject_key(email, Gdk.Key.u);
1345+ GLib.assert (email.text == "a@ubuntu.org");
1346+
1347+ inject_key(email, Gdk.Key.r);
1348+ GLib.assert (email.text == "a@urban.net");
1349+
1350+ inject_key(email, Gdk.Key.BackSpace);
1351+ GLib.assert (email.text == "a@ur");
1352+
1353+ inject_key(email, Gdk.Key.BackSpace);
1354+ GLib.assert (email.text == "a@u");
1355+
1356+ inject_key(email, Gdk.Key.BackSpace);
1357+ GLib.assert (email.text == "a@");
1358+
1359+ inject_key(email, Gdk.Key.c);
1360+ GLib.assert (email.text == "a@canonical.com");
1361+
1362+ inject_key(email, Gdk.Key.a);
1363+ GLib.assert (email.text == "a@canonical.com");
1364+
1365+ inject_key(email, Gdk.Key.n);
1366+ GLib.assert (email.text == "a@canonical.com");
1367+
1368+ inject_key(email, Gdk.Key.d);
1369+ GLib.assert (email.text == "a@candy.com");
1370+
1371+ mw.hide ();
1372+ }
1373+
1374+ public static void greeter_communcation ()
1375+ {
1376+ MainWindow mw = setup ();
1377+ TestList list = mw.stack.top () as TestList;
1378+
1379+ // Wait until remote login appears
1380+ scroll_to_remote_login (list);
1381+
1382+ // Fill in a valid email and password
1383+ // Check there is no error and we moved to the last logged in server
1384+ var email = remote_directory_entry_email_field (list);
1385+ var pwd = remote_directory_entry_password_field (list);
1386+ email.text = "a@canonical.com";
1387+ pwd.text = "password";
1388+ list.selected_entry.respond ({});
1389+ wait_for_scrolling_end (list);
1390+
1391+ while (list.selected_entry.id != "*remote_login*http://coolrdpserver.com")
1392+ do_scroll (list, GreeterList.ScrollTarget.UP);
1393+
1394+ var domain = remote_login_entry_domain_field (list);
1395+ var username = remote_login_entry_username_field (list);
1396+ pwd = remote_login_entry_password_field (list);
1397+ domain.text = "foo";
1398+ username.text = "bar";
1399+ pwd.text = "foobar";
1400+
1401+ UnityGreeter.singleton.show_prompt("remote login:", LightDM.PromptType.QUESTION);
1402+ GLib.assert (UnityGreeter.singleton.last_respond_response == username.text);
1403+ UnityGreeter.singleton.show_prompt("remote host:", LightDM.PromptType.QUESTION);
1404+ GLib.assert (UnityGreeter.singleton.last_respond_response == "http://coolrdpserver.com");
1405+ UnityGreeter.singleton.show_prompt("domain:", LightDM.PromptType.QUESTION);
1406+ GLib.assert (UnityGreeter.singleton.last_respond_response == domain.text);
1407+ UnityGreeter.singleton.show_prompt("password:", LightDM.PromptType.SECRET);
1408+ GLib.assert (UnityGreeter.singleton.last_respond_response == pwd.text);
1409+
1410+ mw.hide ();
1411+ }
1412+
1413+ public static void unsupported_server_type ()
1414+ {
1415+ MainWindow mw = setup ();
1416+ TestList list = mw.stack.top () as TestList;
1417+
1418+ // Wait until remote login appears
1419+ scroll_to_remote_login (list);
1420+
1421+ // Fill in a valid email and password
1422+ // Check there is no error and we moved to the last logged in server
1423+ var email = remote_directory_entry_email_field (list);
1424+ var pwd = remote_directory_entry_password_field (list);
1425+ email.text = "a@canonical.com";
1426+ pwd.text = "password";
1427+ list.selected_entry.respond ({});
1428+ wait_for_scrolling_end (list);
1429+
1430+ while (list.selected_entry.id != "*remote_login*http://notsupportedserver.com")
1431+ do_scroll (list, GreeterList.ScrollTarget.UP);
1432+
1433+ GLib.assert (list.selected_entry.has_errors);
1434+ GLib.assert (!list.selected_entry.sensitive);
1435+
1436+ mw.hide ();
1437+ }
1438+
1439+ static void setup_gsettings()
1440+ {
1441+ try
1442+ {
1443+ var dir = GLib.DirUtils.make_tmp ("unity-greeter-test-XXXXXX");
1444+
1445+ var schema_dir = Path.build_filename(dir, "share", "glib-2.0", "schemas");
1446+ DirUtils.create_with_parents(schema_dir, 0700);
1447+
1448+ var data_dirs = Environment.get_variable("XDG_DATA_DIRS");
1449+ Environment.set_variable("XDG_DATA_DIRS", "%s:%s".printf(Path.build_filename(dir, "share"), data_dirs), true);
1450+
1451+ if (Posix.system("cp ../data/com.canonical.unity-greeter.gschema.xml %s".printf(schema_dir)) != 0)
1452+ warning("Could not copy schema to %s", schema_dir);
1453+
1454+ if (Posix.system("glib-compile-schemas %s".printf(schema_dir)) != 0)
1455+ warning("Could not compile schemas in %s", schema_dir);
1456+
1457+ Environment.set_variable("GSETTINGS_BACKEND", "memory", true);
1458+ }
1459+ catch (Error e)
1460+ {
1461+ debug ("Error setting up gsettings: %s", e.message);
1462+ }
1463+ }
1464+
1465+ public static int main (string[] args)
1466+ {
1467+ Gtk.test_init(ref args);
1468+
1469+ setup_gsettings ();
1470+
1471+ UnityGreeter.singleton = new UnityGreeter();
1472+ UnityGreeter.singleton.test_mode = true;
1473+
1474+ GLib.Test.add_func ("/Simple Navigation", simple_navigation);
1475+ GLib.Test.add_func ("/Remote Login", remote_login);
1476+ GLib.Test.add_func ("/Remote Login with Servers Updated signal", remote_login_servers_updated_signal);
1477+ GLib.Test.add_func ("/Remote Login with Servers Updated signal and not in remote server", remote_login_servers_updated_signal_focus_not_in_remote_server);
1478+ GLib.Test.add_func ("/Remote Login with Login Servers Updated signal", remote_login_login_servers_updated_signal);
1479+ GLib.Test.add_func ("/Remote Login with Login Servers Updated signal and not in removed server", remote_login_login_servers_updated_signal_focus_not_in_removed_server);
1480+ GLib.Test.add_func ("/Remote Login with Remote Login Changed signal", remote_login_remote_login_changed_signal);
1481+ GLib.Test.add_func ("/Remote Login with Remote Login Changed signal and not in changed server", remote_login_remote_login_changed_signalfocus_not_in_changed_server);
1482+ GLib.Test.add_func ("/Remote Login authentication", remote_login_authentication);
1483+ GLib.Test.add_func ("/Remote Login cancel authentication", remote_login_cancel_authentication);
1484+ GLib.Test.add_func ("/Email Autocomplete", email_autocomplete);
1485+ GLib.Test.add_func ("/Greeter Communication", greeter_communcation);
1486+ GLib.Test.add_func ("/Unsupported server type", unsupported_server_type);
1487+
1488+ return GLib.Test.run();
1489+ }
1490+
1491+}
1492
1493=== added file 'tests/unity-greeter.vala'
1494--- tests/unity-greeter.vala 1970-01-01 00:00:00 +0000
1495+++ tests/unity-greeter.vala 2012-09-12 14:04:20 +0000
1496@@ -0,0 +1,128 @@
1497+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
1498+ *
1499+ * Copyright (C) 2011 Canonical Ltd
1500+ *
1501+ * This program is free software: you can redistribute it and/or modify
1502+ * it under the terms of the GNU General Public License version 3 as
1503+ * published by the Free Software Foundation.
1504+ *
1505+ * This program is distributed in the hope that it will be useful,
1506+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1507+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1508+ * GNU General Public License for more details.
1509+ *
1510+ * You should have received a copy of the GNU General Public License
1511+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1512+ *
1513+ * Authored by: Robert Ancell <robert.ancell@canonical.com>
1514+ */
1515+
1516+public const int grid_size = 40;
1517+
1518+public class UnityGreeter
1519+{
1520+ public static UnityGreeter singleton;
1521+
1522+ public signal void show_message (string text, LightDM.MessageType type);
1523+ public signal void show_prompt (string text, LightDM.PromptType type);
1524+ public signal void authentication_complete ();
1525+
1526+ public bool test_mode = false;
1527+ public bool session_started = false;
1528+ public string last_respond_response;
1529+
1530+ public bool is_authenticated ()
1531+ {
1532+ return false;
1533+ }
1534+
1535+ public void authenticate (string? userid = null)
1536+ {
1537+ }
1538+
1539+ public void authenticate_as_guest ()
1540+ {
1541+ }
1542+
1543+ public void authenticate_remote (string? session, string? userid)
1544+ {
1545+ }
1546+
1547+ public void cancel_authentication ()
1548+ {
1549+ }
1550+
1551+ public void respond (string response)
1552+ {
1553+ last_respond_response = response;
1554+ }
1555+
1556+ public string authentication_user ()
1557+ {
1558+ return "";
1559+ }
1560+
1561+ public string default_session_hint ()
1562+ {
1563+ return "";
1564+ }
1565+
1566+ public string select_user_hint ()
1567+ {
1568+ return "";
1569+ }
1570+
1571+ public bool show_manual_login_hint ()
1572+ {
1573+ return false;
1574+ }
1575+
1576+ public bool hide_users_hint ()
1577+ {
1578+ return false;
1579+ }
1580+
1581+ public bool has_guest_account_hint ()
1582+ {
1583+ return false;
1584+ }
1585+
1586+ public void start_session (string? session)
1587+ {
1588+ session_started = true;
1589+ }
1590+
1591+ public void push_list (GreeterList widget)
1592+ {
1593+ }
1594+
1595+ public void pop_list ()
1596+ {
1597+ }
1598+
1599+ public string? get_state (string key)
1600+ {
1601+ return null;
1602+ }
1603+
1604+ public void set_state (string key, string value)
1605+ {
1606+ }
1607+
1608+ public static LightDM.Layout? get_layout_by_name (string name)
1609+ {
1610+ foreach (var layout in LightDM.get_layouts ())
1611+ {
1612+ if (layout.name == name)
1613+ return layout;
1614+ }
1615+ return null;
1616+ }
1617+
1618+ public static void add_style_class (Gtk.Widget widget)
1619+ {
1620+ /* Add style context class lightdm-user-list */
1621+ var ctx = widget.get_style_context ();
1622+ ctx.add_class ("lightdm");
1623+ }
1624+}

Subscribers

People subscribed via source and target branches