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