Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: chrome/test/live_sync/sync_integration_test.py

Issue 7828055: Move sync test code out of chrome/test (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/live_sync/sync_extension_helper.cc ('k') | chrome/test/live_sync/themes_helper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python2.4
2 #
3 # Copyright 2009 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7
8 """A tool to run a chrome sync integration test, used by the buildbot slaves.
9
10 When this is run, the current directory (cwd) should be the outer build
11 directory (e.g., chrome-release/build/).
12
13 For a list of command-line options, call this script with '--help'.
14 """
15
16 __author__ = 'tejasshah@chromium.org'
17
18
19 import logging
20 import optparse
21 import os
22 import re
23 import subprocess
24 import sys
25 import tempfile
26 import time
27 import urllib2
28
29
30 USAGE = '%s [options] [test args]' % os.path.basename(sys.argv[0])
31 HTTP_SERVER_URL = None
32 HTTP_SERVER_PORT = None
33
34
35 class PathNotFound(Exception): pass
36
37
38 def ListSyncTests(test_exe_path):
39 """Returns list of the enabled live sync tests.
40
41 Args:
42 test_exe_path: Absolute path to test exe file.
43
44 Returns:
45 List of the tests that should be run.
46 """
47 command = [test_exe_path]
48 command.append('--gtest_list_tests')
49 proc = subprocess.Popen(
50 command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1)
51 proc.wait()
52 sys.stdout.flush()
53 test_list = []
54 for line in proc.stdout.readlines():
55 if not line.strip():
56 continue
57 elif line.count("."): # A new test collection
58 test_collection = line.split(".")[0].strip();
59 else: # An individual test to run
60 test_name = line.strip()
61 test_list.append("%s.%s" % (test_collection, test_name))
62 logging.info('List of tests to run: %s' % (test_list))
63 return test_list
64
65
66 def GetUrl(command, port):
67 """Prepares the URL with appropriate command to send it to http server.
68
69 Args:
70 command: Command for HTTP server
71 port: Port number as a parameter to the command
72
73 Returns:
74 Formulated URL with the command and parameter.
75 """
76 command_url = (
77 '%s:%s/%s?port=%s'
78 % (HTTP_SERVER_URL, HTTP_SERVER_PORT, command, port))
79 return command_url
80
81
82 def StartSyncServer(port=None):
83 """Starts a chrome sync server.
84
85 Args:
86 port: Port number on which sync server to start
87 (Default value none, in this case it uses random port).
88
89 Returns:
90 If success then port number on which sync server started, else None.
91 """
92 sync_port = None
93 if port:
94 start_sync_server_url = GetUrl('startsyncserver', port)
95 else:
96 start_sync_server_url = (
97 '%s:%s/%s' % (HTTP_SERVER_URL, HTTP_SERVER_PORT, 'startsyncserver'))
98 req = urllib2.Request(start_sync_server_url)
99 try:
100 response = urllib2.urlopen(req)
101 except urllib2.HTTPError, e:
102 logging.error(
103 'Could not start sync server, something went wrong.'
104 'Request URL: %s , Error Code: %s'% (start_sync_server_url, e.code))
105 return sync_port
106 except urllib2.URLError, e:
107 logging.error(
108 'Failed to reach HTTP server.Request URL: %s , Error: %s'
109 % (start_sync_server_url, e.reason))
110 return sync_port
111 else:
112 # Let's read response and parse the sync server port number.
113 output = response.readlines()
114 # Regex to ensure that sync server started and extract the port number.
115 regex = re.compile(
116 ".*not.*running.*on.*port\s*:\s*(\d+).*started.*new.*sync.*server",
117 re.IGNORECASE|re.MULTILINE|re.DOTALL)
118 r = regex.search(output[0])
119 if r:
120 sync_port = r.groups()[0]
121 if sync_port:
122 logging.info(
123 'Started Sync Server Successfully on Port:%s. Request URL: %s , '
124 'Response: %s' % (sync_port, start_sync_server_url, output))
125 response.fp._sock.recv = None
126 response.close()
127 return sync_port
128
129
130 def CheckIfSyncServerRunning(port):
131 """Check the healthz status of a chrome sync server.
132
133 Args:
134 port: Port number on which sync server is running
135
136 Returns:
137 True: If sync server running.
138 False: Otherwise.
139 """
140 sync_server_healthz_url = ('%s:%s/healthz' % (HTTP_SERVER_URL, port))
141 req = urllib2.Request(sync_server_healthz_url)
142 try:
143 response = urllib2.urlopen(req)
144 except urllib2.HTTPError, e:
145 logging.error(
146 'It seems like Sync Server is not running, healthz check failed.'
147 'Request URL: %s , Error Code: %s'% (sync_server_healthz_url, e.code))
148 return False
149 except urllib2.URLError, e:
150 logging.error(
151 'Failed to reach Sync server, healthz check failed.'
152 'Request URL: %s , Error: %s'% (sync_server_healthz_url, e.reason))
153 return False
154 else:
155 logging.info(
156 'Sync Server healthz check Passed.Request URL: %s , Response: %s'
157 % (sync_server_healthz_url, response.readlines()))
158 response.fp._sock.recv = None
159 response.close()
160 return True
161
162
163 def StopSyncServer(port):
164 """Stops a chrome sync server.
165
166 Args:
167 port: Port number on which sync server to Stop
168
169 Returns:
170 Success/Failure as a bool value.
171 """
172 stop_sync_server_url = GetUrl('stopsyncserver', port)
173 req = urllib2.Request(stop_sync_server_url)
174 logging.info("Stopping: %s" % stop_sync_server_url)
175 try:
176 response = urllib2.urlopen(req)
177 except urllib2.HTTPError, e:
178 logging.error(
179 'Could not stop sync server, something went wrong.'
180 'Request URL: %s , Error Code: %s'% (stop_sync_server_url, e.code))
181 return False
182 except urllib2.URLError, e:
183 logging.error(
184 'Failed to reach HTTP server.Request URL: %s , Error: %s'
185 % (stop_sync_server_url, e.reason))
186 return False
187 else:
188 logging.info(
189 'Stopped Sync Server Successfully.Request URL: %s , Response: %s'
190 % (stop_sync_server_url, response.readlines()))
191 response.fp._sock.recv = None
192 response.close()
193 return True
194
195
196 def ShowGtestLikeFailure(test_exe_path, test_name):
197 """Show a gtest-like error when the test can't be run for some reason.
198
199 The scripts responsible for detecting test failures watch for this pattern.
200
201 Args:
202 test_exe_path: Absolute path to the test exe file.
203 test_name: The name of the test that wasn't run.
204 """
205 print '[ RUN ] %s.%s' % (os.path.basename(test_exe_path), test_name)
206 print '[ FAILED ] %s.%s' % (os.path.basename(test_exe_path), test_name)
207
208
209 def RunCommand(command):
210 """Runs the command list, printing its output and returning its exit status.
211
212 Prints the given command (which should be a list of one or more strings),
213 then runs it and prints its stdout and stderr together to stdout,
214 line-buffered, converting line endings to CRLF (see note below). Waits for
215 the command to terminate and returns its status.
216
217 Args:
218 command: Command to run.
219
220 Returns:
221 Process exit code.
222 """
223 print '\n' + subprocess.list2cmdline(command) + '\n',
224 proc = subprocess.Popen(command, stdout=subprocess.PIPE,
225 stderr=subprocess.STDOUT, bufsize=1)
226 last_flush_time = time.time()
227 while proc.poll() == None:
228 # Note that Windows Python converts \n to \r\n automatically whenever it
229 # encounters it written to a text file (including stdout). The only way
230 # around it is to write to a binary file, which isn't feasible for stdout.
231 # So we're stuck with \r\n here even though we explicitly write \n. (We
232 # could write \r instead, which doesn't get converted to \r\n, but that's
233 # probably more troublesome for people trying to read the files.)
234 line = proc.stdout.readline()
235 if line:
236 # The comma at the end tells python to not add \n, which is \r\n on
237 # Windows.
238 print line.rstrip() + '\n',
239 # Python on windows writes the buffer only when it reaches 4k. This is
240 # not fast enough. Flush each 10 seconds instead.
241 if time.time() - last_flush_time >= 10:
242 sys.stdout.flush()
243 last_flush_time = time.time()
244 sys.stdout.flush()
245 # Write the remaining buffer.
246 for line in proc.stdout.readlines():
247 print line.rstrip() + '\n',
248 sys.stdout.flush()
249 return proc.returncode
250
251
252 def RunOneTest(test_exe_path, test_name, username, password):
253 """Run one live sync test after setting up a fresh server environment.
254
255 Args:
256 test_exe_path: Absolute path to test exe file.
257 test_name: the name of the one test to run.
258 username: test account username.
259 password: test account password.
260
261 Returns:
262 Zero for suceess.
263 Non-zero for failure.
264 """
265 def LogTestNotRun(message):
266 ShowGtestLikeFailure(test_exe_path, test_name)
267 logging.info('\n\n%s did not run because %s' % (test_name, message))
268
269 try:
270 logging.info('\n\n*************************************')
271 logging.info('%s Start' % (test_name))
272 sync_port = StartSyncServer()
273 if not sync_port:
274 LogTestNotRun('starting the sync server failed.')
275 return 1
276 if not CheckIfSyncServerRunning(sync_port):
277 LogTestNotRun('sync server running check failed.')
278 return 1
279 logging.info('Verified that sync server is running on port: %s', sync_port)
280 user_dir = GenericSetup(test_name)
281 logging.info('Created user data dir %s' % (user_dir))
282 command = [
283 test_exe_path,
284 '--gtest_filter='+ test_name,
285 '--user-data-dir=' + user_dir,
286 '--sync-user-for-test=' + username,
287 '--sync-password-for-test=' + password,
288 '--sync-url=' + HTTP_SERVER_URL + ':' + sync_port]
289 logging.info(
290 '%s will run with command: %s'
291 % (test_name, subprocess.list2cmdline(command)))
292 result = RunCommand(command)
293 StopSyncServer(sync_port)
294 return result
295 finally:
296 logging.info('%s End' % (test_name))
297
298
299 def GenericSetup(test_name):
300 """Generic setup for running one test.
301
302 Args:
303 test_name: The name of a test that is about to be run.
304
305 Returns:
306 user_dir: Absolute path to user data dir created for the test.
307 """
308 user_dir = tempfile.mkdtemp(prefix=test_name + '.')
309 return user_dir
310
311
312 def main_win(options, args):
313 """Main Function for win32 platform which drives the test here.
314
315 Using the target build configuration, run the executable given in the
316 first non-option argument, passing any following arguments to that
317 executable.
318
319 Args:
320 options: Option parameters.
321 args: Test arguments.
322
323 Returns:
324 Result: Zero for success/ Non-zero for failure.
325 """
326 final_result = 0
327 test_exe = 'sync_integration_tests.exe'
328 build_dir = os.path.abspath(options.build_dir)
329 test_exe_path = os.path.join(build_dir, options.target, test_exe)
330 if not os.path.exists(test_exe_path):
331 raise PathNotFound('Unable to find %s' % test_exe_path)
332 test_list = ListSyncTests(test_exe_path)
333 for test_name in test_list:
334 result = RunOneTest(
335 test_exe_path, test_name, options.sync_test_username,
336 options.sync_test_password)
337 # If any single test fails then final result should be failure
338 if result != 0:
339 final_result = result
340 return final_result
341
342 if '__main__' == __name__:
343 # Initialize logging.
344 log_level = logging.INFO
345 logging.basicConfig(
346 level=log_level, format='%(asctime)s %(filename)s:%(lineno)-3d'
347 ' %(levelname)s %(message)s', datefmt='%y%m%d %H:%M:%S')
348
349 option_parser = optparse.OptionParser(usage=USAGE)
350
351 # Since the trailing program to run may have has command-line args of its
352 # own, we need to stop parsing when we reach the first positional argument.
353 option_parser.disable_interspersed_args()
354
355 option_parser.add_option(
356 '', '--target', default='Release', help='Build target (Debug or Release)'
357 ' Default value Release.')
358 option_parser.add_option(
359 '', '--build-dir', help='Path to main build directory'
360 '(the parent of the Release or Debug directory).')
361 option_parser.add_option(
362 '', '--http-server-url', help='Path to http server that can be used to'
363 ' start/stop sync server e.g. http://http_server_url_without_port')
364 option_parser.add_option(
365 '', '--http-server-port', help='Port on which http server is running'
366 ' e.g. 1010')
367 option_parser.add_option(
368 '', '--sync-test-username', help='Test username e.g. foo@gmail.com')
369 option_parser.add_option(
370 '', '--sync-test-password', help='Password for the test account')
371 options, args = option_parser.parse_args()
372 if not options.sync_test_password:
373 # Check along side this script under src/ first, and then check in
374 # the user profile dir.
375 password_file_path = os.path.join(
376 os.path.dirname(__file__),'sync_password')
377 if (not os.path.exists(password_file_path)):
378 password_file_path = os.path.join(
379 os.environ['USERPROFILE'], 'sync_password')
380
381 if os.path.exists(password_file_path):
382 fs = open(password_file_path, 'r')
383 lines = fs.readlines()
384 if len(lines)==1:
385 options.sync_test_password = lines[0].strip()
386 else:
387 sys.stderr.write('sync_password file is not in required format.\n')
388 sys.exit(1)
389 else:
390 sys.stderr.write(
391 'Missing required parameter- sync_test_password, please fix it.\n')
392 sys.exit(1)
393 if (not options.build_dir or not options.http_server_url or
394 not options.http_server_port or not options.sync_test_username):
395 sys.stderr.write('Missing required parameter, please fix it.\n')
396 option_parser.print_help()
397 sys.exit(1)
398 if sys.platform == 'win32':
399 HTTP_SERVER_URL = options.http_server_url
400 HTTP_SERVER_PORT = options.http_server_port
401 sys.exit(main_win(options, args))
402 else:
403 sys.stderr.write('Unknown sys.platform value %s\n' % repr(sys.platform))
404 sys.exit(1)
OLDNEW
« no previous file with comments | « chrome/test/live_sync/sync_extension_helper.cc ('k') | chrome/test/live_sync/themes_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698