xref: /aosp_15_r20/external/autotest/site_utils/lxc/unittest_http.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright 2017 The Chromium OS Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Lifrom contextlib import contextmanager
5*9c5db199SXin Li
6*9c5db199SXin Liimport logging
7*9c5db199SXin Liimport multiprocessing
8*9c5db199SXin Liimport os
9*9c5db199SXin Liimport shutil
10*9c5db199SXin Liimport tempfile
11*9c5db199SXin Liimport six.moves.socketserver
12*9c5db199SXin Liimport six.moves.SimpleHTTPServer
13*9c5db199SXin Li
14*9c5db199SXin Liimport common
15*9c5db199SXin Lifrom autotest_lib.client.bin import utils
16*9c5db199SXin Lifrom autotest_lib.client.common_lib import error
17*9c5db199SXin Lifrom autotest_lib.site_utils.lxc import constants
18*9c5db199SXin Li
19*9c5db199SXin Li
20*9c5db199SXin Li@contextmanager
21*9c5db199SXin Lidef serve_locally(file_path):
22*9c5db199SXin Li    """Starts an http server on the localhost, to serve the given file.
23*9c5db199SXin Li
24*9c5db199SXin Li    Copies the given file to a temporary location, then starts a local http
25*9c5db199SXin Li    server to serve that file.  Intended for use with unit tests that require
26*9c5db199SXin Li    some URL to download a file (see testInstallSsp as an example).
27*9c5db199SXin Li
28*9c5db199SXin Li    @param file_path: The path of the file to serve.
29*9c5db199SXin Li
30*9c5db199SXin Li    @return The URL at which the file will be served.
31*9c5db199SXin Li    """
32*9c5db199SXin Li    p = None
33*9c5db199SXin Li    try:
34*9c5db199SXin Li        # Copy the target file into a tmpdir for serving.
35*9c5db199SXin Li        tmpdir = tempfile.mkdtemp()
36*9c5db199SXin Li        shutil.copy(file_path, tmpdir)
37*9c5db199SXin Li
38*9c5db199SXin Li        httpd = six.moves.socketserver.TCPServer(
39*9c5db199SXin Li                ('', 0), six.moves.SimpleHTTPServer.SimpleHTTPRequestHandler)
40*9c5db199SXin Li        port = httpd.socket.getsockname()[1]
41*9c5db199SXin Li
42*9c5db199SXin Li        # Start the http daemon in the tmpdir to serve the file.
43*9c5db199SXin Li        def serve():
44*9c5db199SXin Li            """Serves the tmpdir."""
45*9c5db199SXin Li            os.chdir(tmpdir)
46*9c5db199SXin Li            httpd.serve_forever()
47*9c5db199SXin Li        p = multiprocessing.Process(target=serve)
48*9c5db199SXin Li        p.daemon = True
49*9c5db199SXin Li        p.start()
50*9c5db199SXin Li
51*9c5db199SXin Li        utils.poll_for_condition(
52*9c5db199SXin Li                condition=lambda: http_up(port),
53*9c5db199SXin Li                timeout=constants.NETWORK_INIT_TIMEOUT,
54*9c5db199SXin Li                sleep_interval=constants.NETWORK_INIT_CHECK_INTERVAL)
55*9c5db199SXin Li        url = 'http://127.0.0.1:{port}/{filename}'.format(
56*9c5db199SXin Li                port=port, filename=os.path.basename(file_path))
57*9c5db199SXin Li        logging.debug('Serving %s as %s', file_path, url)
58*9c5db199SXin Li        yield url
59*9c5db199SXin Li    finally:
60*9c5db199SXin Li        if p is not None:
61*9c5db199SXin Li            p.terminate()
62*9c5db199SXin Li        shutil.rmtree(tmpdir)
63*9c5db199SXin Li
64*9c5db199SXin Li
65*9c5db199SXin Lidef http_up(port):
66*9c5db199SXin Li    """Checks for an http server on localhost:port.
67*9c5db199SXin Li
68*9c5db199SXin Li    @param port: The port to check.
69*9c5db199SXin Li    """
70*9c5db199SXin Li    try:
71*9c5db199SXin Li        utils.run('curl --head http://127.0.0.1:%d' % port)
72*9c5db199SXin Li        return True
73*9c5db199SXin Li    except error.CmdError:
74*9c5db199SXin Li        return False
75