chromium/native_client_sdk/src/build_tools/tests/test_server.py

# Copyright 2012 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import multiprocessing
import os
import SimpleHTTPServer


class LocalHTTPServer(object):
  """Class to start a local HTTP server as a child process."""

  def __init__(self, serve_dir):
    parent_conn, child_conn = multiprocessing.Pipe()
    self.process = multiprocessing.Process(target=_HTTPServerProcess,
                                           args=(child_conn, serve_dir))
    self.process.start()
    if parent_conn.poll(10):  # wait 10 seconds
      self.port = parent_conn.recv()
    else:
      raise Exception('Unable to launch HTTP server.')

    self.conn = parent_conn

  def Shutdown(self):
    """Send a message to the child HTTP server process and wait for it to
        finish."""
    self.conn.send(False)
    self.process.join()

  def GetURL(self, rel_url):
    """Get the full url for a file on the local HTTP server.

    Args:
      rel_url: A URL fragment to convert to a full URL. For example,
          GetURL('foobar.baz') -> 'http://localhost:1234/foobar.baz'
    """
    return 'http://localhost:%d/%s' % (self.port, rel_url)


class QuietHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  def log_message(self, msg_format, *args):
    pass


def _HTTPServerProcess(conn, serve_dir):
  """Run a local httpserver with a randomly-chosen port.

  This function assumes it is run as a child process using multiprocessing.

  Args:
    conn: A connection to the parent process. The child process sends
        the local port, and waits for a message from the parent to
        stop serving.
    serve_dir: The directory to serve. All files are accessible through
       http://localhost:<port>/path/to/filename.
  """
  import BaseHTTPServer

  os.chdir(serve_dir)
  httpd = BaseHTTPServer.HTTPServer(('', 0), QuietHTTPRequestHandler)
  conn.send(httpd.server_address[1])  # the chosen port number
  httpd.timeout = 0.5  # seconds
  running = True
  while running:
    httpd.handle_request()
    if conn.poll():
      running = conn.recv()
  conn.close()