#!/usr/bin/env python3 # -*- coding: utf-8 -*- #*************************************************************************** # _ _ ____ _ # Project ___| | | | _ \| | # / __| | | | |_) | | # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # # Copyright (C) Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at https://curl.se/docs/copyright.html. # # You may opt to use, copy, modify, merge, publish, distribute and/or sell # copies of the Software, and permit persons to whom the Software is # furnished to do so, under the terms of the COPYING file. # # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # KIND, either express or implied. # # SPDX-License-Identifier: curl # ########################################################################### # import pytest import json import logging import os import re import shutil import subprocess from datetime import timedelta, datetime from typing import List, Optional, Dict, Union from urllib.parse import urlparse from . import ExecResult from .env import Env log = logging.getLogger(__name__) class LocalClient: def __init__(self, name: str, env: Env, run_dir: Optional[str] = None, timeout: Optional[float] = None, run_env: Optional[Dict[str,str]] = None): self.name = name self.path = os.path.join(env.project_dir, f'tests/http/clients/{name}') self.env = env self._run_env= run_env self._timeout = timeout if timeout else env.test_timeout self._curl = os.environ['CURL'] if 'CURL' in os.environ else env.curl self._run_dir = run_dir if run_dir else os.path.join(env.gen_dir, name) self._stdoutfile = f'{self._run_dir}/stdout' self._stderrfile = f'{self._run_dir}/stderr' self._rmrf(self._run_dir) self._mkpath(self._run_dir) @property def run_dir(self) -> str: return self._run_dir @property def stderr_file(self) -> str: return self._stderrfile def exists(self) -> bool: return os.path.exists(self.path) def download_file(self, i: int) -> str: return os.path.join(self._run_dir, f'download_{i}.data') def _rmf(self, path): if os.path.exists(path): return os.remove(path) def _rmrf(self, path): if os.path.exists(path): return shutil.rmtree(path) def _mkpath(self, path): if not os.path.exists(path): return os.makedirs(path) def run(self, args): self._rmf(self._stdoutfile) self._rmf(self._stderrfile) start = datetime.now() exception = None myargs = [self.path] myargs.extend(args) try: with open(self._stdoutfile, 'w') as cout: with open(self._stderrfile, 'w') as cerr: p = subprocess.run(myargs, stderr=cerr, stdout=cout, cwd=self._run_dir, shell=False, input=None, env=self._run_env, timeout=self._timeout) exitcode = p.returncode except subprocess.TimeoutExpired: log.warning(f'Timeout after {self._timeout}s: {args}') exitcode = -1 exception = 'TimeoutExpired' coutput = open(self._stdoutfile).readlines() cerrput = open(self._stderrfile).readlines() return ExecResult(args=myargs, exit_code=exitcode, exception=exception, stdout=coutput, stderr=cerrput, duration=datetime.now() - start) def dump_logs(self): lines = [] lines.append('>>--stdout ----------------------------------------------\n') lines.extend(open(self._stdoutfile).readlines()) lines.append('>>--stderr ----------------------------------------------\n') lines.extend(open(self._stderrfile).readlines()) lines.append('<<-------------------------------------------------------\n') return ''.join(lines)