summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eissing <stefan@eissing.org>2023-03-17 09:30:02 +0100
committerDaniel Stenberg <daniel@haxx.se>2023-03-26 17:41:46 +0200
commit9d107b6954d5690731f86702105d2e29421f7226 (patch)
treeb853d32ed2faa342e1d891cababa422087ba9329
parent9c469942e2ffa2551400bf000663da149e611907 (diff)
downloadcurl-9d107b6954d5690731f86702105d2e29421f7226.tar.gz
tests/http: add timeout to running curl in test cases
- we had a CI case once where `curl` seemingly did not return and it was hard to guess what happened. - make curl execution in test cases time out after 60 seconds Closes #10783
-rw-r--r--tests/http/scorecard.py1
-rw-r--r--tests/http/testenv/curl.py32
-rw-r--r--tests/http/testenv/env.py9
-rw-r--r--tests/http/testenv/httpd.py3
4 files changed, 34 insertions, 11 deletions
diff --git a/tests/http/scorecard.py b/tests/http/scorecard.py
index 21dafe181..d9f789c9f 100644
--- a/tests/http/scorecard.py
+++ b/tests/http/scorecard.py
@@ -374,6 +374,7 @@ class ScoreCard:
rv = 0
self.env = Env()
self.env.setup()
+ self.env.test_timeout = None
self.httpd = None
self.nghttpx = None
self.caddy = None
diff --git a/tests/http/testenv/curl.py b/tests/http/testenv/curl.py
index ec832eca0..13c4f8465 100644
--- a/tests/http/testenv/curl.py
+++ b/tests/http/testenv/curl.py
@@ -45,9 +45,11 @@ class ExecResult:
def __init__(self, args: List[str], exit_code: int,
stdout: List[str], stderr: List[str],
duration: Optional[timedelta] = None,
- with_stats: bool = False):
+ with_stats: bool = False,
+ exception: Optional[str] = None):
self._args = args
self._exit_code = exit_code
+ self._exception = exception
self._stdout = stdout
self._stderr = stderr
self._duration = duration if duration is not None else timedelta()
@@ -69,7 +71,8 @@ class ExecResult:
pass
def __repr__(self):
- return f"ExecResult[code={self.exit_code}, args={self._args}, stdout={self._stdout}, stderr={self._stderr}]"
+ return f"ExecResult[code={self.exit_code}, exception={self._exception}, "\
+ f"args={self._args}, stdout={self._stdout}, stderr={self._stderr}]"
def _parse_stats(self):
self._stats = []
@@ -78,7 +81,6 @@ class ExecResult:
self._stats.append(json.loads(l))
except:
log.error(f'not a JSON stat: {l}')
- log.error(f'stdout is: {"".join(self._stdout)}')
break
@property
@@ -197,8 +199,10 @@ class CurlClient:
'h3': '--http3-only',
}
- def __init__(self, env: Env, run_dir: Optional[str] = None):
+ def __init__(self, env: Env, run_dir: Optional[str] = None,
+ timeout: Optional[float] = None):
self.env = 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, 'curl')
self._stdoutfile = f'{self._run_dir}/curl.stdout'
@@ -320,14 +324,22 @@ class CurlClient:
self._rmf(self._headerfile)
self._rmf(self._tracefile)
start = datetime.now()
- with open(self._stdoutfile, 'w') as cout:
- with open(self._stderrfile, 'w') as cerr:
- p = subprocess.run(args, stderr=cerr, stdout=cout,
- cwd=self._run_dir, shell=False,
- input=intext.encode() if intext else None)
+ exception = None
+ try:
+ with open(self._stdoutfile, 'w') as cout:
+ with open(self._stderrfile, 'w') as cerr:
+ p = subprocess.run(args, stderr=cerr, stdout=cout,
+ cwd=self._run_dir, shell=False,
+ input=intext.encode() if intext else None,
+ timeout=self._timeout)
+ exitcode = p.returncode
+ except subprocess.TimeoutExpired as e:
+ 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=args, exit_code=p.returncode,
+ return ExecResult(args=args, exit_code=exitcode, exception=exception,
stdout=coutput, stderr=cerrput,
duration=datetime.now() - start,
with_stats=with_stats)
diff --git a/tests/http/testenv/env.py b/tests/http/testenv/env.py
index bf08104d3..c34d79129 100644
--- a/tests/http/testenv/env.py
+++ b/tests/http/testenv/env.py
@@ -281,6 +281,7 @@ class Env:
self._verbose = pytestconfig.option.verbose \
if pytestconfig is not None else 0
self._ca = None
+ self._test_timeout = 60.0 # seconds
def issue_certs(self):
if self._ca is None:
@@ -306,6 +307,14 @@ class Env:
return self._verbose
@property
+ def test_timeout(self) -> Optional[float]:
+ return self._test_timeout
+
+ @test_timeout.setter
+ def test_timeout(self, val: Optional[float]):
+ self._test_timeout = val
+
+ @property
def gen_dir(self) -> str:
return self.CONFIG.gen_dir
diff --git a/tests/http/testenv/httpd.py b/tests/http/testenv/httpd.py
index 4c7874581..5b20d31e2 100644
--- a/tests/http/testenv/httpd.py
+++ b/tests/http/testenv/httpd.py
@@ -171,7 +171,8 @@ class Httpd:
return False
def wait_live(self, timeout: timedelta):
- curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir,
+ timeout=timeout.total_seconds())
try_until = datetime.now() + timeout
while datetime.now() < try_until:
r = curl.http_get(url=f'http://{self.env.domain1}:{self.env.http_port}/')