xref: /aosp_15_r20/external/curl/tests/http/testenv/client.py (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6236dae4SAndroid Build Coastguard Worker# -*- coding: utf-8 -*-
3*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
4*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
5*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
6*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
7*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
8*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
9*6236dae4SAndroid Build Coastguard Worker#
10*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
11*6236dae4SAndroid Build Coastguard Worker#
12*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
13*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
14*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
15*6236dae4SAndroid Build Coastguard Worker#
16*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
17*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
18*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
19*6236dae4SAndroid Build Coastguard Worker#
20*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
22*6236dae4SAndroid Build Coastguard Worker#
23*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
24*6236dae4SAndroid Build Coastguard Worker#
25*6236dae4SAndroid Build Coastguard Worker###########################################################################
26*6236dae4SAndroid Build Coastguard Worker#
27*6236dae4SAndroid Build Coastguard Workerimport logging
28*6236dae4SAndroid Build Coastguard Workerimport os
29*6236dae4SAndroid Build Coastguard Workerimport shutil
30*6236dae4SAndroid Build Coastguard Workerimport subprocess
31*6236dae4SAndroid Build Coastguard Workerfrom datetime import datetime
32*6236dae4SAndroid Build Coastguard Workerfrom typing import Optional, Dict
33*6236dae4SAndroid Build Coastguard Worker
34*6236dae4SAndroid Build Coastguard Workerfrom . import ExecResult
35*6236dae4SAndroid Build Coastguard Workerfrom .env import Env
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker
38*6236dae4SAndroid Build Coastguard Workerlog = logging.getLogger(__name__)
39*6236dae4SAndroid Build Coastguard Worker
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Workerclass LocalClient:
42*6236dae4SAndroid Build Coastguard Worker
43*6236dae4SAndroid Build Coastguard Worker    def __init__(self, name: str, env: Env, run_dir: Optional[str] = None,
44*6236dae4SAndroid Build Coastguard Worker                 timeout: Optional[float] = None,
45*6236dae4SAndroid Build Coastguard Worker                 run_env: Optional[Dict[str,str]] = None):
46*6236dae4SAndroid Build Coastguard Worker        self.name = name
47*6236dae4SAndroid Build Coastguard Worker        self.path = os.path.join(env.build_dir, f'tests/http/clients/{name}')
48*6236dae4SAndroid Build Coastguard Worker        self.env = env
49*6236dae4SAndroid Build Coastguard Worker        self._run_env = run_env
50*6236dae4SAndroid Build Coastguard Worker        self._timeout = timeout if timeout else env.test_timeout
51*6236dae4SAndroid Build Coastguard Worker        self._curl = os.environ['CURL'] if 'CURL' in os.environ else env.curl
52*6236dae4SAndroid Build Coastguard Worker        self._run_dir = run_dir if run_dir else os.path.join(env.gen_dir, name)
53*6236dae4SAndroid Build Coastguard Worker        self._stdoutfile = f'{self._run_dir}/stdout'
54*6236dae4SAndroid Build Coastguard Worker        self._stderrfile = f'{self._run_dir}/stderr'
55*6236dae4SAndroid Build Coastguard Worker        self._rmrf(self._run_dir)
56*6236dae4SAndroid Build Coastguard Worker        self._mkpath(self._run_dir)
57*6236dae4SAndroid Build Coastguard Worker
58*6236dae4SAndroid Build Coastguard Worker    @property
59*6236dae4SAndroid Build Coastguard Worker    def run_dir(self) -> str:
60*6236dae4SAndroid Build Coastguard Worker        return self._run_dir
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Worker    @property
63*6236dae4SAndroid Build Coastguard Worker    def stderr_file(self) -> str:
64*6236dae4SAndroid Build Coastguard Worker        return self._stderrfile
65*6236dae4SAndroid Build Coastguard Worker
66*6236dae4SAndroid Build Coastguard Worker    def exists(self) -> bool:
67*6236dae4SAndroid Build Coastguard Worker        return os.path.exists(self.path)
68*6236dae4SAndroid Build Coastguard Worker
69*6236dae4SAndroid Build Coastguard Worker    def download_file(self, i: int) -> str:
70*6236dae4SAndroid Build Coastguard Worker        return os.path.join(self._run_dir, f'download_{i}.data')
71*6236dae4SAndroid Build Coastguard Worker
72*6236dae4SAndroid Build Coastguard Worker    def _rmf(self, path):
73*6236dae4SAndroid Build Coastguard Worker        if os.path.exists(path):
74*6236dae4SAndroid Build Coastguard Worker            return os.remove(path)
75*6236dae4SAndroid Build Coastguard Worker
76*6236dae4SAndroid Build Coastguard Worker    def _rmrf(self, path):
77*6236dae4SAndroid Build Coastguard Worker        if os.path.exists(path):
78*6236dae4SAndroid Build Coastguard Worker            return shutil.rmtree(path)
79*6236dae4SAndroid Build Coastguard Worker
80*6236dae4SAndroid Build Coastguard Worker    def _mkpath(self, path):
81*6236dae4SAndroid Build Coastguard Worker        if not os.path.exists(path):
82*6236dae4SAndroid Build Coastguard Worker            return os.makedirs(path)
83*6236dae4SAndroid Build Coastguard Worker
84*6236dae4SAndroid Build Coastguard Worker    def run(self, args):
85*6236dae4SAndroid Build Coastguard Worker        self._rmf(self._stdoutfile)
86*6236dae4SAndroid Build Coastguard Worker        self._rmf(self._stderrfile)
87*6236dae4SAndroid Build Coastguard Worker        start = datetime.now()
88*6236dae4SAndroid Build Coastguard Worker        exception = None
89*6236dae4SAndroid Build Coastguard Worker        myargs = [self.path]
90*6236dae4SAndroid Build Coastguard Worker        myargs.extend(args)
91*6236dae4SAndroid Build Coastguard Worker        run_env = None
92*6236dae4SAndroid Build Coastguard Worker        if self._run_env:
93*6236dae4SAndroid Build Coastguard Worker            run_env = self._run_env.copy()
94*6236dae4SAndroid Build Coastguard Worker            for key in ['CURL_DEBUG']:
95*6236dae4SAndroid Build Coastguard Worker                if key in os.environ and key not in run_env:
96*6236dae4SAndroid Build Coastguard Worker                    run_env[key] = os.environ[key]
97*6236dae4SAndroid Build Coastguard Worker        try:
98*6236dae4SAndroid Build Coastguard Worker            with open(self._stdoutfile, 'w') as cout, open(self._stderrfile, 'w') as cerr:
99*6236dae4SAndroid Build Coastguard Worker                p = subprocess.run(myargs, stderr=cerr, stdout=cout,
100*6236dae4SAndroid Build Coastguard Worker                                   cwd=self._run_dir, shell=False,
101*6236dae4SAndroid Build Coastguard Worker                                   input=None, env=run_env,
102*6236dae4SAndroid Build Coastguard Worker                                   timeout=self._timeout)
103*6236dae4SAndroid Build Coastguard Worker                exitcode = p.returncode
104*6236dae4SAndroid Build Coastguard Worker        except subprocess.TimeoutExpired:
105*6236dae4SAndroid Build Coastguard Worker            log.warning(f'Timeout after {self._timeout}s: {args}')
106*6236dae4SAndroid Build Coastguard Worker            exitcode = -1
107*6236dae4SAndroid Build Coastguard Worker            exception = 'TimeoutExpired'
108*6236dae4SAndroid Build Coastguard Worker        coutput = open(self._stdoutfile).readlines()
109*6236dae4SAndroid Build Coastguard Worker        cerrput = open(self._stderrfile).readlines()
110*6236dae4SAndroid Build Coastguard Worker        return ExecResult(args=myargs, exit_code=exitcode, exception=exception,
111*6236dae4SAndroid Build Coastguard Worker                          stdout=coutput, stderr=cerrput,
112*6236dae4SAndroid Build Coastguard Worker                          duration=datetime.now() - start)
113*6236dae4SAndroid Build Coastguard Worker
114*6236dae4SAndroid Build Coastguard Worker    def dump_logs(self):
115*6236dae4SAndroid Build Coastguard Worker        lines = []
116*6236dae4SAndroid Build Coastguard Worker        lines.append('>>--stdout ----------------------------------------------\n')
117*6236dae4SAndroid Build Coastguard Worker        lines.extend(open(self._stdoutfile).readlines())
118*6236dae4SAndroid Build Coastguard Worker        lines.append('>>--stderr ----------------------------------------------\n')
119*6236dae4SAndroid Build Coastguard Worker        lines.extend(open(self._stderrfile).readlines())
120*6236dae4SAndroid Build Coastguard Worker        lines.append('<<-------------------------------------------------------\n')
121*6236dae4SAndroid Build Coastguard Worker        return ''.join(lines)
122