Merge "Allow adding arbitrary properties to OutputPage"
[lhc/web/wiklou.git] / tests / selenium / SeleniumServerManager.php
1 <?php
2 /**
3 * Selenium server manager
4 *
5 * @file
6 * @ingroup Testing
7 * Copyright (C) 2010 Dan Nessett <dnessett@yahoo.com>
8 * http://citizendium.org/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * http://www.gnu.org/copyleft/gpl.html
24 *
25 * @addtogroup Testing
26 */
27
28 class SeleniumServerManager {
29 private $SeleniumStartServer = false;
30 private $OS = '';
31 private $SeleniumServerPid = 'NaN';
32 private $SeleniumServerPort = 4444;
33 private $SeleniumServerStartTimeout = 10; // 10 secs.
34 private $SeleniumServerExecPath;
35
36 public function __construct( $startServer,
37 $serverPort,
38 $serverExecPath ) {
39 $this->OS = (string)PHP_OS;
40
41 if ( isset( $startServer ) ) {
42 $this->SeleniumStartServer = $startServer;
43 }
44
45 if ( isset( $serverPort ) ) {
46 $this->SeleniumServerPort = $serverPort;
47 }
48
49 if ( isset( $serverExecPath ) ) {
50 $this->SeleniumServerExecPath = $serverExecPath;
51 }
52
53 return;
54 }
55
56 // Getters for certain private attributes. No setters, since they
57 // should not change after the manager object is created.
58
59 public function getSeleniumStartServer() {
60 return $this->SeleniumStartServer;
61 }
62
63 public function getSeleniumServerPort() {
64 return $this->SeleniumServerPort;
65 }
66
67 public function getSeleniumServerPid() {
68 return $this->SeleniumServerPid;
69 }
70
71 // Changing value of SeleniumStartServer allows starting server after
72 // creation of the class instance. Only allow setting SeleniumStartServer
73 // to true, since after server is started, it is shut down by stop().
74
75 public function setSeleniumStartServer( $startServer ) {
76 if ( $startServer == true ) {
77 $this->SeleniumStartServer = true;
78 }
79 }
80
81 // return values are: 1) started - server started, 2) failed -
82 // server not started, 3) running - instructed to start server, but
83 // server already running
84
85 public function start() {
86
87 if ( !$this->SeleniumStartServer ) {
88 return 'failed';
89 }
90
91 // commented out cases are untested
92
93 switch ( $this->OS ) {
94 case "Linux":
95 # case' CYGWIN_NT-5.1':
96 case 'Darwin':
97 # case 'FreeBSD':
98 # case 'HP-UX':
99 # case 'IRIX64':
100 # case 'NetBSD':
101 # case 'OpenBSD':
102 # case 'SunOS':
103 # case 'Unix':
104 // *nix based OS
105 return $this->startServerOnUnix();
106 break;
107 case "Windows":
108 case "WIN32":
109 case "WINNT":
110 // Windows
111 return $this->startServerOnWindows();
112 break;
113 default:
114 // An untested OS
115 return 'failed';
116 break;
117 }
118 }
119
120 public function stop() {
121
122 // commented out cases are untested
123
124 switch ( $this->OS ) {
125 case "Linux":
126 # case' CYGWIN_NT-5.1':
127 case 'Darwin':
128 # case 'FreeBSD':
129 # case 'HP-UX':
130 # case 'IRIX64':
131 # case 'NetBSD':
132 # case 'OpenBSD':
133 # case 'SunOS':
134 # case 'Unix':
135 // *nix based OS
136 return $this->stopServerOnUnix();
137 break;
138 case "Windows":
139 case "WIN32":
140 case "WINNT":
141 // Windows
142 return $this->stopServerOnWindows();
143 break;
144 default:
145 // An untested OS
146 return 'failed';
147 break;
148 }
149 }
150
151 private function startServerOnUnix() {
152
153 $output = array();
154 $user = $_ENV['USER'];
155 // @todo FIXME: This should be a little more generalized :)
156 if ( PHP_OS == 'Darwin' ) {
157 // Mac OS X's ps barfs on the 'w' param, but doesn't need it.
158 $ps = "ps -U %s";
159 } else {
160 // Good on Linux
161 $ps = "ps -U %s w";
162 }
163 $psCommand = sprintf( $ps, escapeshellarg( $user ) );
164 exec( $psCommand . " | grep -i selenium-server", $output );
165
166 // Start server. If there is already a server running,
167 // return running.
168
169 if ( isset( $this->SeleniumServerExecPath ) ) {
170 $found = 0;
171 foreach ( $output as $string ) {
172 $found += preg_match(
173 '~^(.*)java(.+)-jar(.+)selenium-server~',
174 $string );
175 }
176 if ( $found == 0 ) {
177
178 // Didn't find the selenium server. Start it up.
179 // First set up comamand line suffix.
180 // NB: $! is pid of last job run in background
181 // The echo guarentees it is put into $op when
182 // the exec command is run.
183
184 $commandSuffix = ' > /dev/null 2>&1' . ' & echo $!';
185 $portText = ' -port ' . $this->SeleniumServerPort;
186 $command = "java -jar " .
187 escapeshellarg( $this->SeleniumServerExecPath ) .
188 $portText . $commandSuffix;
189 exec( $command, $op );
190 $pid = (int)$op[0];
191 if ( $pid != "" ) {
192 $this->SeleniumServerPid = $pid;
193 } else {
194 $this->SeleniumServerPid = 'NaN';
195 // Server start failed.
196 return 'failed';
197 }
198 // Wait for the server to startup and listen
199 // on its port. Note: this solution kinda
200 // stinks, since it uses a wait loop - dnessett
201
202 wfSuppressWarnings();
203 for ( $cnt = 1;
204 $cnt <= $this->SeleniumServerStartTimeout;
205 $cnt++ ) {
206 $fp = fsockopen( 'localhost',
207 $this->SeleniumServerPort,
208 $errno, $errstr, 0 );
209 if ( !$fp ) {
210 sleep( 1 );
211 continue;
212 // Server start succeeded.
213 } else {
214 fclose( $fp );
215 return 'started';
216 }
217 }
218 wfRestoreWarnings();
219 echo ( "Starting Selenium server timed out.\n" );
220 return 'failed';
221 } else {
222 // server already running.
223 return 'running';
224 }
225
226 }
227
228 // No Server execution path defined.
229 return 'failed';
230 }
231
232 private function startServerOnWindows() {
233 // Unimplemented.
234 return 'failed';
235 }
236
237 private function stopServerOnUnix() {
238
239 if ( !empty( $this->SeleniumServerPid ) &&
240 $this->SeleniumServerPid != 'NaN'
241 ) {
242 exec( "kill -9 " . $this->SeleniumServerPid );
243 return 'stopped';
244 } else {
245 return 'failed';
246 }
247 }
248
249 private function stopServerOnWindows() {
250 // Unimplemented.
251 return 'failed';
252
253 }
254 }