| Index: build/android/devil/android/ports.py
|
| diff --git a/build/android/devil/android/ports.py b/build/android/devil/android/ports.py
|
| deleted file mode 100644
|
| index eff30ced0f53ec0845070fb37aef02e5d9993146..0000000000000000000000000000000000000000
|
| --- a/build/android/devil/android/ports.py
|
| +++ /dev/null
|
| @@ -1,178 +0,0 @@
|
| -# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -"""Functions that deal with local and device ports."""
|
| -
|
| -import contextlib
|
| -import fcntl
|
| -import httplib
|
| -import logging
|
| -import os
|
| -import socket
|
| -import traceback
|
| -
|
| -# The net test server is started from port 10201.
|
| -_TEST_SERVER_PORT_FIRST = 10201
|
| -_TEST_SERVER_PORT_LAST = 30000
|
| -# A file to record next valid port of test server.
|
| -_TEST_SERVER_PORT_FILE = '/tmp/test_server_port'
|
| -_TEST_SERVER_PORT_LOCKFILE = '/tmp/test_server_port.lock'
|
| -
|
| -
|
| -# The following two methods are used to allocate the port source for various
|
| -# types of test servers. Because some net-related tests can be run on shards at
|
| -# same time, it's important to have a mechanism to allocate the port
|
| -# process-safe. In here, we implement the safe port allocation by leveraging
|
| -# flock.
|
| -def ResetTestServerPortAllocation():
|
| - """Resets the port allocation to start from TEST_SERVER_PORT_FIRST.
|
| -
|
| - Returns:
|
| - Returns True if reset successes. Otherwise returns False.
|
| - """
|
| - try:
|
| - with open(_TEST_SERVER_PORT_FILE, 'w') as fp:
|
| - fp.write('%d' % _TEST_SERVER_PORT_FIRST)
|
| - if os.path.exists(_TEST_SERVER_PORT_LOCKFILE):
|
| - os.unlink(_TEST_SERVER_PORT_LOCKFILE)
|
| - return True
|
| - except Exception: # pylint: disable=broad-except
|
| - logging.exception('Error while resetting port allocation')
|
| - return False
|
| -
|
| -
|
| -def AllocateTestServerPort():
|
| - """Allocates a port incrementally.
|
| -
|
| - Returns:
|
| - Returns a valid port which should be in between TEST_SERVER_PORT_FIRST and
|
| - TEST_SERVER_PORT_LAST. Returning 0 means no more valid port can be used.
|
| - """
|
| - port = 0
|
| - ports_tried = []
|
| - try:
|
| - fp_lock = open(_TEST_SERVER_PORT_LOCKFILE, 'w')
|
| - fcntl.flock(fp_lock, fcntl.LOCK_EX)
|
| - # Get current valid port and calculate next valid port.
|
| - if not os.path.exists(_TEST_SERVER_PORT_FILE):
|
| - ResetTestServerPortAllocation()
|
| - with open(_TEST_SERVER_PORT_FILE, 'r+') as fp:
|
| - port = int(fp.read())
|
| - ports_tried.append(port)
|
| - while not IsHostPortAvailable(port):
|
| - port += 1
|
| - ports_tried.append(port)
|
| - if (port > _TEST_SERVER_PORT_LAST or
|
| - port < _TEST_SERVER_PORT_FIRST):
|
| - port = 0
|
| - else:
|
| - fp.seek(0, os.SEEK_SET)
|
| - fp.write('%d' % (port + 1))
|
| - except Exception: # pylint: disable=broad-except
|
| - logging.exception('ERror while allocating port')
|
| - finally:
|
| - if fp_lock:
|
| - fcntl.flock(fp_lock, fcntl.LOCK_UN)
|
| - fp_lock.close()
|
| - if port:
|
| - logging.info('Allocate port %d for test server.', port)
|
| - else:
|
| - logging.error('Could not allocate port for test server. '
|
| - 'List of ports tried: %s', str(ports_tried))
|
| - return port
|
| -
|
| -
|
| -def IsHostPortAvailable(host_port):
|
| - """Checks whether the specified host port is available.
|
| -
|
| - Args:
|
| - host_port: Port on host to check.
|
| -
|
| - Returns:
|
| - True if the port on host is available, otherwise returns False.
|
| - """
|
| - s = socket.socket()
|
| - try:
|
| - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
| - s.bind(('', host_port))
|
| - s.close()
|
| - return True
|
| - except socket.error:
|
| - return False
|
| -
|
| -
|
| -def IsDevicePortUsed(device, device_port, state=''):
|
| - """Checks whether the specified device port is used or not.
|
| -
|
| - Args:
|
| - device: A DeviceUtils instance.
|
| - device_port: Port on device we want to check.
|
| - state: String of the specified state. Default is empty string, which
|
| - means any state.
|
| -
|
| - Returns:
|
| - True if the port on device is already used, otherwise returns False.
|
| - """
|
| - base_urls = ('127.0.0.1:%d' % device_port, 'localhost:%d' % device_port)
|
| - netstat_results = device.RunShellCommand(
|
| - ['netstat', '-a'], check_return=True, large_output=True)
|
| - for single_connect in netstat_results:
|
| - # Column 3 is the local address which we want to check with.
|
| - connect_results = single_connect.split()
|
| - if connect_results[0] != 'tcp':
|
| - continue
|
| - if len(connect_results) < 6:
|
| - raise Exception('Unexpected format while parsing netstat line: ' +
|
| - single_connect)
|
| - is_state_match = connect_results[5] == state if state else True
|
| - if connect_results[3] in base_urls and is_state_match:
|
| - return True
|
| - return False
|
| -
|
| -
|
| -def IsHttpServerConnectable(host, port, tries=3, command='GET', path='/',
|
| - expected_read='', timeout=2):
|
| - """Checks whether the specified http server is ready to serve request or not.
|
| -
|
| - Args:
|
| - host: Host name of the HTTP server.
|
| - port: Port number of the HTTP server.
|
| - tries: How many times we want to test the connection. The default value is
|
| - 3.
|
| - command: The http command we use to connect to HTTP server. The default
|
| - command is 'GET'.
|
| - path: The path we use when connecting to HTTP server. The default path is
|
| - '/'.
|
| - expected_read: The content we expect to read from the response. The default
|
| - value is ''.
|
| - timeout: Timeout (in seconds) for each http connection. The default is 2s.
|
| -
|
| - Returns:
|
| - Tuple of (connect status, client error). connect status is a boolean value
|
| - to indicate whether the server is connectable. client_error is the error
|
| - message the server returns when connect status is false.
|
| - """
|
| - assert tries >= 1
|
| - for i in xrange(0, tries):
|
| - client_error = None
|
| - try:
|
| - with contextlib.closing(httplib.HTTPConnection(
|
| - host, port, timeout=timeout)) as http:
|
| - # Output some debug information when we have tried more than 2 times.
|
| - http.set_debuglevel(i >= 2)
|
| - http.request(command, path)
|
| - r = http.getresponse()
|
| - content = r.read()
|
| - if r.status == 200 and r.reason == 'OK' and content == expected_read:
|
| - return (True, '')
|
| - client_error = ('Bad response: %s %s version %s\n ' %
|
| - (r.status, r.reason, r.version) +
|
| - '\n '.join([': '.join(h) for h in r.getheaders()]))
|
| - except (httplib.HTTPException, socket.error) as e:
|
| - # Probably too quick connecting: try again.
|
| - exception_error_msgs = traceback.format_exception_only(type(e), e)
|
| - if exception_error_msgs:
|
| - client_error = ''.join(exception_error_msgs)
|
| - # Only returns last client_error.
|
| - return (False, client_error or 'Timeout')
|
|
|