2
* Compiz Autopilot GTest Acceptance Tests
4
* Copyright (C) 2013 Canonical Ltd.
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
* Sam Spilsbury <smspillaz@gmail.com>
25
#include <boost/noncopyable.hpp>
36
#include <gtest/gtest.h>
38
using ::testing::ValuesIn;
39
using ::testing::WithParamInterface;
50
if (pipe2 (mPipe, O_CLOEXEC) == -1)
51
throw std::runtime_error (strerror (errno));
57
close (mPipe[0]) == -1)
58
std::cerr << "mPipe[0] " << strerror (errno) << std::endl;
61
close (mPipe[1]) == -1)
62
std::cerr << "mPipe[0] " << strerror (errno) << std::endl;
65
/* Read end descriptor is read-only */
71
/* Write end descriptor is writable, we need to close it
72
* from other objects */
83
class FileDescriptorBackup :
88
FileDescriptorBackup (int fd) :
92
mBackupFd = dup (mOriginalFd);
96
throw std::runtime_error (strerror (errno));
99
~FileDescriptorBackup ()
101
/* Redirect backed up fd to old fd location */
103
dup2 (mBackupFd, mOriginalFd) == -1)
104
std::cerr << "Failed to restore file descriptor "
105
<< strerror (errno) << std::endl;
114
class RedirectedFileDescriptor :
119
RedirectedFileDescriptor (int from,
124
/* Make 'to' take the old file descriptor's place */
125
if (dup2 (to, from) == -1)
126
throw std::runtime_error (strerror (errno));
129
~RedirectedFileDescriptor ()
133
std::cerr << "Failed to close redirect-to file descriptor "
134
<< strerror (errno) << std::endl;
145
pid_t launchBinary (const std::string &executable,
150
FileDescriptorBackup stderr (STDERR_FILENO);
151
FileDescriptorBackup stdout (STDOUT_FILENO);
153
/* Close the originals once they have been backed up
154
* We have to do this here and not in the FileDescriptorBackup
155
* constructors because of an order-of-operations issue -
156
* namely if we close an original file descriptor name
157
* before duplicating another one, then there's a possibility
158
* that the duplicated other one will get the same name as
159
* the one we just closed, making us unable to restore
160
* the closed one properly */
161
if (close (STDERR_FILENO) == -1)
162
throw std::runtime_error (strerror (errno));
164
if (close (STDOUT_FILENO) == -1)
165
throw std::runtime_error (strerror (errno));
167
/* Replace the current process stderr and stdout with the write end
168
* of the pipes. Now when someone tries to write to stderr or stdout
169
* they'll write to our pipes instead */
170
RedirectedFileDescriptor pipedStderr (STDERR_FILENO, stderrWriteEnd);
171
RedirectedFileDescriptor pipedStdout (STDOUT_FILENO, stdoutWriteEnd);
173
/* Fork process, child gets a copy of the pipe write ends
174
* - the original pipe write ends will be closed on exec
175
* but the duplicated write ends now taking the place of
176
* stderr and stdout will not be */
177
pid_t child = fork ();
182
if (execvpe (executable.c_str (),
183
const_cast <char * const *> (argv),
186
std::cerr << "execvpe failed with error "
195
/* Parent process - error */
196
else if (child == -1)
197
throw std::runtime_error (strerror (errno));
199
/* The old file descriptors for the stderr and stdout
200
* are put back in place, and pipe write ends closed
201
* as the child is using them at return */
206
int launchBinaryAndWaitForReturn (const std::string &executable,
212
pid_t child = launchBinary (executable,
219
/* Wait around for the child to get a signal */
220
pid_t waitChild = waitpid (child, &status, 0);
221
if (waitChild == child)
223
/* If it died unexpectedly, say so */
224
if (WIFSIGNALED (status))
226
std::stringstream ss;
227
ss << "child killed by signal "
228
<< WTERMSIG (status);
229
throw std::runtime_error (ss.str ());
234
/* waitpid () failed */
235
throw std::runtime_error (strerror (errno));
238
/* Keep going until it exited */
239
} while (!WIFEXITED (status) && !WIFSIGNALED (status));
241
/* Return the exit code */
242
return WEXITSTATUS (status);
245
const char *autopilot = "/usr/bin/autopilot";
246
const char *runOpt = "run";
247
const char *dashV = "-v";
250
class CompizAutopilotAcceptanceTest :
251
public ::testing::Test,
252
public ::testing::WithParamInterface <const char *>
256
CompizAutopilotAcceptanceTest ();
257
const char ** GetAutopilotArgv ();
258
void PrintChildStderr ();
259
void PrintChildStdout ();
263
std::vector <const char *> autopilotArgv;
264
Pipe childStdoutPipe;
265
Pipe childStderrPipe;
268
CompizAutopilotAcceptanceTest::CompizAutopilotAcceptanceTest ()
270
autopilotArgv.push_back (autopilot);
271
autopilotArgv.push_back (runOpt);
272
autopilotArgv.push_back (dashV);
273
autopilotArgv.push_back (GetParam ());
274
autopilotArgv.push_back (NULL);
278
CompizAutopilotAcceptanceTest::GetAutopilotArgv ()
280
return &autopilotArgv[0];
285
std::string FdToString (int fd)
289
int bufferSize = 4096;
290
char buffer[bufferSize];
297
pfd.events = POLLIN | POLLERR | POLLHUP;
301
/* Check for 10ms if there's anything waiting to be read */
302
int nfds = poll (&pfd, 1, 10);
305
throw std::runtime_error (strerror (errno));
309
/* Read as much as we have allocated for */
310
count = read (fd, (void *) buffer, bufferSize - 1);
312
/* Something failed, bail */
314
throw std::runtime_error (strerror (errno));
316
/* Always null-terminate */
317
buffer[count] = '\0';
319
/* Add it to the output */
324
/* There's nothing on the pipe, assume EOF */
328
/* Keep going until there's nothing left */
329
} while (count != 0);
336
CompizAutopilotAcceptanceTest::PrintChildStderr ()
338
std::string output = FdToString (childStderrPipe.ReadEnd ());
340
std::cout << "[== TEST ERRORS ==]" << std::endl
346
CompizAutopilotAcceptanceTest::PrintChildStdout ()
348
std::string output = FdToString (childStdoutPipe.ReadEnd ());
350
std::cout << "[== TEST MESSAGES ==]" << std::endl
355
TEST_P (CompizAutopilotAcceptanceTest, AutopilotTest)
357
std::string scopedTraceMsg ("Running Autopilot Test");
358
scopedTraceMsg += GetParam ();
360
int status = launchBinaryAndWaitForReturn (std::string (autopilot),
362
childStderrPipe.WriteEnd (),
363
childStdoutPipe.WriteEnd ());
365
EXPECT_EQ (status, 0) << "expected exit status of 0";
374
/* Extra space here to align with gtest output */
375
std::cout << "[AUTOPILOT ] Pass test " << GetParam () << std::endl;
381
const char *AutopilotTests[] =
383
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_clicking_icon_twice_initiates_spread",
384
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_expo_launcher_icon_initiates_expo",
385
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_expo_launcher_icon_terminates_expo",
386
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_launcher_activate_last_focused_window",
387
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_unminimize_initially_minimized_windows",
388
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_unminimize_minimized_immediately_after_show_windows",
389
"unity.tests.launcher.test_icon_behavior.LauncherIconsTests.test_while_in_scale_mode_the_dash_will_still_open",
390
"unity.tests.test_dash.DashRevealWithSpreadTests.test_command_lens_opens_when_in_spread",
391
"unity.tests.test_dash.DashRevealWithSpreadTests.test_dash_closes_on_spread",
392
"unity.tests.test_dash.DashRevealWithSpreadTests.test_dash_opens_when_in_spread",
393
"unity.tests.test_dash.DashRevealWithSpreadTests.test_lens_opens_when_in_spread",
394
"unity.tests.test_hud.HudBehaviorTests.test_alt_arrow_keys_not_eaten",
395
"unity.tests.test_panel.PanelCrossMonitorsTests.test_panel_title_updates_moving_window",
396
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_close_inactive_when_clicked_in_another_monitor",
397
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_dont_show_for_maximized_window_on_mouse_in",
398
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_dont_show_in_other_monitors_when_dash_is_open",
399
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_dont_show_in_other_monitors_when_hud_is_open",
400
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_minimize_inactive_when_clicked_in_another_monitor",
401
"unity.tests.test_panel.PanelCrossMonitorsTests.test_window_buttons_unmaximize_inactive_when_clicked_in_another_monitor",
402
"unity.tests.test_panel.PanelGrabAreaTests.test_focus_the_maximized_window_works",
403
"unity.tests.test_panel.PanelGrabAreaTests.test_lower_the_maximized_window_works",
404
"unity.tests.test_panel.PanelGrabAreaTests.test_panels_dont_steal_keynav_foucs_from_hud",
405
"unity.tests.test_panel.PanelGrabAreaTests.test_unmaximize_from_grab_area_works",
406
"unity.tests.test_panel.PanelHoverTests.test_menus_show_for_maximized_window_on_mouse_in_btn_area",
407
"unity.tests.test_panel.PanelHoverTests.test_menus_show_for_maximized_window_on_mouse_in_grab_area",
408
"unity.tests.test_panel.PanelHoverTests.test_menus_show_for_maximized_window_on_mouse_in_menu_area",
409
"unity.tests.test_panel.PanelHoverTests.test_only_menus_show_for_restored_window_on_mouse_in_grab_area",
410
"unity.tests.test_panel.PanelHoverTests.test_only_menus_show_for_restored_window_on_mouse_in_menu_area",
411
"unity.tests.test_panel.PanelHoverTests.test_only_menus_show_for_restored_window_on_mouse_in_window_btn_area",
412
"unity.tests.test_panel.PanelMenuTests.test_menus_dont_show_for_maximized_window_on_mouse_out",
413
"unity.tests.test_panel.PanelMenuTests.test_menus_dont_show_for_restored_window_on_mouse_out",
414
"unity.tests.test_panel.PanelMenuTests.test_menus_dont_show_if_a_new_application_window_is_opened",
415
"unity.tests.test_panel.PanelMenuTests.test_menus_show_for_maximized_window_on_mouse_in",
416
"unity.tests.test_panel.PanelMenuTests.test_menus_show_for_restored_window_on_mouse_in",
417
"unity.tests.test_panel.PanelMenuTests.test_menus_shows_when_new_application_is_opened",
418
"unity.tests.test_panel.PanelTitleTests.test_panel_shows_app_title_with_maximised_app",
419
"unity.tests.test_panel.PanelTitleTests.test_panel_title_doesnt_change_with_switcher",
420
"unity.tests.test_panel.PanelTitleTests.test_panel_title_on_empty_desktop",
421
"unity.tests.test_panel.PanelTitleTests.test_panel_title_updates_on_maximized_window_title_changes",
422
"unity.tests.test_panel.PanelTitleTests.test_panel_title_updates_when_switching_to_maximized_app",
423
"unity.tests.test_panel.PanelTitleTests.test_panel_title_with_maximized_application",
424
"unity.tests.test_panel.PanelTitleTests.test_panel_title_with_maximized_window_restored_child",
425
"unity.tests.test_panel.PanelTitleTests.test_panel_title_with_restored_application",
426
"unity.tests.test_panel.PanelWindowButtonsTests.test_double_click_unmaximize_window",
427
"unity.tests.test_panel.PanelWindowButtonsTests.test_minimize_button_disabled_for_non_minimizable_windows",
428
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_dont_show_for_maximized_window_on_mouse_out",
429
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_dont_show_for_restored_window",
430
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_dont_show_for_restored_window_with_mouse_in_panel",
431
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_dont_show_on_empty_desktop",
432
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_minimize_button_works_for_window",
433
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_show_for_maximized_window_on_mouse_in",
434
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_unmaximize_button_works_for_window",
435
"unity.tests.test_panel.PanelWindowButtonsTests.test_window_buttons_unmaximize_follows_fitts_law",
436
"unity.tests.test_showdesktop.ShowDesktopTests.test_showdesktop_hides_apps",
437
"unity.tests.test_showdesktop.ShowDesktopTests.test_showdesktop_switcher",
438
"unity.tests.test_showdesktop.ShowDesktopTests.test_showdesktop_unhides_apps",
439
"unity.tests.test_showdesktop.ShowDesktopTests.test_unhide_single_app",
440
"unity.tests.test_spread.SpreadTests.test_scale_application_windows",
441
"unity.tests.test_spread.SpreadTests.test_scaled_window_closes_on_close_button_click",
442
"unity.tests.test_spread.SpreadTests.test_scaled_window_closes_on_middle_click",
443
"unity.tests.test_spread.SpreadTests.test_scaled_window_is_focused_on_click",
444
"unity.tests.test_switcher.SwitcherDetailsModeTests.test_detail_mode_selects_last_active_window",
445
"unity.tests.test_switcher.SwitcherDetailsModeTests.test_detail_mode_selects_third_window",
446
"unity.tests.test_switcher.SwitcherDetailsTests.test_no_details_for_apps_on_different_workspace",
447
"unity.tests.test_switcher.SwitcherTests.test_application_window_is_fake_decorated",
448
"unity.tests.test_switcher.SwitcherTests.test_application_window_is_fake_decorated_in_detail_mode",
449
"unity.tests.test_switcher.SwitcherWindowsManagementTests.test_switcher_raises_only_last_focused_window",
450
"unity.tests.test_switcher.SwitcherWindowsManagementTests.test_switcher_rises_next_window_of_same_application",
451
"unity.tests.test_switcher.SwitcherWindowsManagementTests.test_switcher_rises_other_application",
452
"unity.tests.test_switcher.SwitcherWorkspaceTests.test_switcher_all_mode_shows_all_apps",
453
"unity.tests.test_switcher.SwitcherWorkspaceTests.test_switcher_can_switch_to_minimised_window",
454
"unity.tests.test_switcher.SwitcherWorkspaceTests.test_switcher_is_disabled_when_wall_plugin_active",
455
"unity.tests.test_switcher.SwitcherWorkspaceTests.test_switcher_shows_current_workspace_only"
460
INSTANTIATE_TEST_CASE_P (UnityIntegrationAutopilotTests, CompizAutopilotAcceptanceTest,
461
ValuesIn (AutopilotTests));