mirror of
https://github.com/curl/curl.git
synced 2026-08-02 07:50:28 +03:00
tests: address mutable class vars and naive datetime in Python code
Mark Python mutable class variables with ClassVar, to denote that the danger this can cause has been considered. Since any change made to these in any object affects all other objects, this can cause locality errors. However, as used in the test suite, they are are never modified and so they are annotated as being intended. Always set a timezone in datetime objects, as mixing naive and timezone-aware object can cause errors. These fix ruff rules DTZ005, RUF012.
This commit is contained in:
parent
b151a0bb90
commit
e13362c20a
13 changed files with 81 additions and 78 deletions
|
|
@ -26,6 +26,8 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import ClassVar, Dict, List
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from testenv import CurlClient, Env, LocalClient
|
from testenv import CurlClient, Env, LocalClient
|
||||||
|
|
@ -33,15 +35,16 @@ from testenv import CurlClient, Env, LocalClient
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
class TLSDefs:
|
class TLSDefs:
|
||||||
TLS_VERSIONS = ['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']
|
TLS_VERSIONS: ClassVar[List[str]] = ['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']
|
||||||
TLS_VERSION_IDS = {
|
TLS_VERSION_IDS: ClassVar[Dict[str, int]] = {
|
||||||
'TLSv1': 0x301,
|
'TLSv1': 0x301,
|
||||||
'TLSv1.1': 0x302,
|
'TLSv1.1': 0x302,
|
||||||
'TLSv1.2': 0x303,
|
'TLSv1.2': 0x303,
|
||||||
'TLSv1.3': 0x304
|
'TLSv1.3': 0x304
|
||||||
}
|
}
|
||||||
CURL_ARG_MIN_VERSION_ID = {
|
CURL_ARG_MIN_VERSION_ID: ClassVar[Dict[str, int]] = {
|
||||||
'none': 0x0,
|
'none': 0x0,
|
||||||
'tlsv1': 0x301,
|
'tlsv1': 0x301,
|
||||||
'tlsv1.0': 0x301,
|
'tlsv1.0': 0x301,
|
||||||
|
|
@ -49,7 +52,7 @@ class TLSDefs:
|
||||||
'tlsv1.2': 0x303,
|
'tlsv1.2': 0x303,
|
||||||
'tlsv1.3': 0x304,
|
'tlsv1.3': 0x304,
|
||||||
}
|
}
|
||||||
CURL_ARG_MAX_VERSION_ID = {
|
CURL_ARG_MAX_VERSION_ID: ClassVar[Dict[str, int]] = {
|
||||||
'none': 0x0,
|
'none': 0x0,
|
||||||
'1.0': 0x301,
|
'1.0': 0x301,
|
||||||
'1.1': 0x302,
|
'1.1': 0x302,
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
@ -59,8 +59,8 @@ class WsServer:
|
||||||
def check_alive(self, env, port, timeout=Env.SERVER_TIMEOUT):
|
def check_alive(self, env, port, timeout=Env.SERVER_TIMEOUT):
|
||||||
curl = CurlClient(env=env)
|
curl = CurlClient(env=env)
|
||||||
url = f'http://localhost:{port}/'
|
url = f'http://localhost:{port}/'
|
||||||
end = datetime.now() + timedelta(seconds=timeout)
|
end = datetime.now(timezone.utc) + timedelta(seconds=timeout)
|
||||||
while datetime.now() < end:
|
while datetime.now(timezone.utc) < end:
|
||||||
r = curl.http_download(urls=[url])
|
r = curl.http_download(urls=[url])
|
||||||
if r.exit_code == 0:
|
if r.exit_code == 0:
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ import os
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from json import JSONEncoder
|
from json import JSONEncoder
|
||||||
from typing import Dict
|
from typing import ClassVar, Dict
|
||||||
|
|
||||||
from .curl import CurlClient
|
from .curl import CurlClient
|
||||||
from .env import Env
|
from .env import Env
|
||||||
|
|
@ -40,7 +40,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Caddy:
|
class Caddy:
|
||||||
|
|
||||||
PORT_SPECS = {
|
PORT_SPECS: ClassVar[Dict[str, int]] = {
|
||||||
'caddy': socket.SOCK_STREAM,
|
'caddy': socket.SOCK_STREAM,
|
||||||
'caddys': socket.SOCK_STREAM,
|
'caddys': socket.SOCK_STREAM,
|
||||||
}
|
}
|
||||||
|
|
@ -137,8 +137,8 @@ class Caddy:
|
||||||
|
|
||||||
def wait_dead(self, timeout: timedelta):
|
def wait_dead(self, timeout: timedelta):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'https://{self.env.domain1}:{self.port}/'
|
check_url = f'https://{self.env.domain1}:{self.port}/'
|
||||||
r = curl.http_get(url=check_url)
|
r = curl.http_get(url=check_url)
|
||||||
if r.exit_code != 0:
|
if r.exit_code != 0:
|
||||||
|
|
@ -150,8 +150,8 @@ class Caddy:
|
||||||
|
|
||||||
def wait_live(self, timeout: timedelta):
|
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)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'https://{self.env.domain1}:{self.port}/'
|
check_url = f'https://{self.env.domain1}:{self.port}/'
|
||||||
r = curl.http_get(url=check_url)
|
r = curl.http_get(url=check_url)
|
||||||
if r.exit_code == 0:
|
if r.exit_code == 0:
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ class CertStore:
|
||||||
(cert.not_valid_before_utc > now)):
|
(cert.not_valid_before_utc > now)):
|
||||||
return None
|
return None
|
||||||
except AttributeError: # older python
|
except AttributeError: # older python
|
||||||
now = datetime.now()
|
now = datetime.now(timezone.utc)
|
||||||
if check_valid and \
|
if check_valid and \
|
||||||
((cert.not_valid_after < now) or
|
((cert.not_valid_after < now) or
|
||||||
(cert.not_valid_before > now)):
|
(cert.not_valid_before > now)):
|
||||||
|
|
@ -422,10 +422,10 @@ class TestCA:
|
||||||
pubkey = pkey.public_key()
|
pubkey = pkey.public_key()
|
||||||
issuer_subject = issuer_subject if issuer_subject is not None else subject
|
issuer_subject = issuer_subject if issuer_subject is not None else subject
|
||||||
|
|
||||||
valid_from = datetime.now()
|
valid_from = datetime.now(timezone.utc)
|
||||||
if valid_until_delta is not None:
|
if valid_until_delta is not None:
|
||||||
valid_from += valid_from_delta
|
valid_from += valid_from_delta
|
||||||
valid_until = datetime.now()
|
valid_until = datetime.now(timezone.utc)
|
||||||
if valid_until_delta is not None:
|
if valid_until_delta is not None:
|
||||||
valid_until += valid_until_delta
|
valid_until += valid_until_delta
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from . import ExecResult
|
from . import ExecResult
|
||||||
|
|
@ -81,7 +81,7 @@ class LocalClient:
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
self._rmf(self._stdoutfile)
|
self._rmf(self._stdoutfile)
|
||||||
self._rmf(self._stderrfile)
|
self._rmf(self._stderrfile)
|
||||||
start = datetime.now()
|
start = datetime.now(timezone.utc)
|
||||||
exception = None
|
exception = None
|
||||||
myargs = [self.path, self.name]
|
myargs = [self.path, self.name]
|
||||||
myargs.extend(args)
|
myargs.extend(args)
|
||||||
|
|
@ -107,7 +107,7 @@ class LocalClient:
|
||||||
cerrput = ferr.readlines()
|
cerrput = ferr.readlines()
|
||||||
return ExecResult(args=myargs, exit_code=exitcode, exception=exception,
|
return ExecResult(args=myargs, exit_code=exitcode, exception=exception,
|
||||||
stdout=coutput, stderr=cerrput,
|
stdout=coutput, stderr=cerrput,
|
||||||
duration=datetime.now() - start)
|
duration=datetime.now(timezone.utc) - start)
|
||||||
|
|
||||||
def dump_logs(self):
|
def dump_logs(self):
|
||||||
lines = []
|
lines = []
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ from datetime import datetime, timedelta, timezone
|
||||||
from functools import cmp_to_key
|
from functools import cmp_to_key
|
||||||
from statistics import fmean, mean
|
from statistics import fmean, mean
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
@ -47,7 +47,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class RunProfile:
|
class RunProfile:
|
||||||
|
|
||||||
STAT_KEYS = ['cpu', 'rss', 'vsz']
|
STAT_KEYS: ClassVar[List[str]] = ['cpu', 'rss', 'vsz']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def AverageStats(cls, profiles: List['RunProfile']):
|
def AverageStats(cls, profiles: List['RunProfile']):
|
||||||
|
|
@ -76,7 +76,7 @@ class RunProfile:
|
||||||
return self._stats
|
return self._stats
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
elapsed = datetime.now() - self._started_at
|
elapsed = datetime.now(timezone.utc) - self._started_at
|
||||||
try:
|
try:
|
||||||
if self._psu is None:
|
if self._psu is None:
|
||||||
self._psu = psutil.Process(pid=self._pid)
|
self._psu = psutil.Process(pid=self._pid)
|
||||||
|
|
@ -92,7 +92,7 @@ class RunProfile:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
self._duration = datetime.now() - self._started_at
|
self._duration = datetime.now(timezone.utc) - self._started_at
|
||||||
if len(self._samples) > 0:
|
if len(self._samples) > 0:
|
||||||
weights = [s['time'].total_seconds() for s in self._samples]
|
weights = [s['time'].total_seconds() for s in self._samples]
|
||||||
self._stats = {}
|
self._stats = {}
|
||||||
|
|
@ -605,7 +605,7 @@ class ExecResult:
|
||||||
|
|
||||||
class CurlClient:
|
class CurlClient:
|
||||||
|
|
||||||
ALPN_ARG = {
|
ALPN_ARG: ClassVar[Dict[str, str]] = {
|
||||||
'http/0.9': '--http0.9',
|
'http/0.9': '--http0.9',
|
||||||
'http/1.0': '--http1.0',
|
'http/1.0': '--http1.0',
|
||||||
'http/1.1': '--http1.1',
|
'http/1.1': '--http1.1',
|
||||||
|
|
@ -1028,7 +1028,7 @@ class CurlClient:
|
||||||
if with_tcpdump:
|
if with_tcpdump:
|
||||||
tcpdump = RunTcpDump(self.env, self._run_dir)
|
tcpdump = RunTcpDump(self.env, self._run_dir)
|
||||||
tcpdump.start()
|
tcpdump.start()
|
||||||
started_at = datetime.now()
|
started_at = datetime.now(timezone.utc)
|
||||||
try:
|
try:
|
||||||
with open(self._stdoutfile, 'w') as cout, open(self._stderrfile, 'w') as cerr:
|
with open(self._stdoutfile, 'w') as cout, open(self._stderrfile, 'w') as cerr:
|
||||||
if with_profile:
|
if with_profile:
|
||||||
|
|
@ -1051,7 +1051,7 @@ class CurlClient:
|
||||||
p.wait(timeout=ptimeout)
|
p.wait(timeout=ptimeout)
|
||||||
break
|
break
|
||||||
except subprocess.TimeoutExpired as e:
|
except subprocess.TimeoutExpired as e:
|
||||||
if end_at and datetime.now() >= end_at:
|
if end_at and datetime.now(timezone.utc) >= end_at:
|
||||||
p.kill()
|
p.kill()
|
||||||
raise subprocess.TimeoutExpired(cmd=args, timeout=self._timeout) from e
|
raise subprocess.TimeoutExpired(cmd=args, timeout=self._timeout) from e
|
||||||
profile.sample()
|
profile.sample()
|
||||||
|
|
@ -1067,13 +1067,13 @@ class CurlClient:
|
||||||
env=self._run_env, check=False)
|
env=self._run_env, check=False)
|
||||||
exitcode = p.returncode
|
exitcode = p.returncode
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
now = datetime.now()
|
now = datetime.now(timezone.utc)
|
||||||
duration = now - started_at
|
duration = now - started_at
|
||||||
log.warning(f'Timeout at {now} after {duration.total_seconds()}s '
|
log.warning(f'Timeout at {now} after {duration.total_seconds()}s '
|
||||||
f'(configured {self._timeout}s): {args}')
|
f'(configured {self._timeout}s): {args}')
|
||||||
exitcode = -1
|
exitcode = -1
|
||||||
exception = 'TimeoutExpired'
|
exception = 'TimeoutExpired'
|
||||||
ended_at = datetime.now()
|
ended_at = datetime.now(timezone.utc)
|
||||||
if tcpdump:
|
if tcpdump:
|
||||||
tcpdump.finish()
|
tcpdump.finish()
|
||||||
if perf:
|
if perf:
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import os
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from . import CurlClient
|
from . import CurlClient
|
||||||
|
|
@ -137,8 +137,8 @@ class Dante:
|
||||||
timeout=timeout.total_seconds(), socks_args=[
|
timeout=timeout.total_seconds(), socks_args=[
|
||||||
'--socks5', f'127.0.0.1:{self._port}'
|
'--socks5', f'127.0.0.1:{self._port}'
|
||||||
])
|
])
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
r = curl.http_get(url=f'http://{self.env.domain1}:{self.env.http_port}/')
|
r = curl.http_get(url=f'http://{self.env.domain1}:{self.env.http_port}/')
|
||||||
if r.exit_code == 0:
|
if r.exit_code == 0:
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import os
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from .env import Env
|
from .env import Env
|
||||||
|
|
@ -133,8 +133,8 @@ class Dnsd:
|
||||||
return self.wait_live(timeout=timedelta(seconds=Env.SERVER_TIMEOUT))
|
return self.wait_live(timeout=timedelta(seconds=Env.SERVER_TIMEOUT))
|
||||||
|
|
||||||
def wait_live(self, timeout: timedelta):
|
def wait_live(self, timeout: timedelta):
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
if os.path.exists(self._log_file):
|
if os.path.exists(self._log_file):
|
||||||
return True
|
return True
|
||||||
time.sleep(.1)
|
time.sleep(.1)
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ import signal
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict, Optional
|
from typing import ClassVar, Dict, Optional
|
||||||
|
|
||||||
from .curl import CurlClient
|
from .curl import CurlClient
|
||||||
from .env import Env
|
from .env import Env
|
||||||
|
|
@ -181,12 +181,12 @@ class H2o:
|
||||||
running = self._process
|
running = self._process
|
||||||
self._process = None
|
self._process = None
|
||||||
os.kill(running.pid, signal.SIGQUIT)
|
os.kill(running.pid, signal.SIGQUIT)
|
||||||
end_wait = datetime.now() + timedelta(seconds=5)
|
end_wait = datetime.now(timezone.utc) + timedelta(seconds=5)
|
||||||
exited = False
|
exited = False
|
||||||
if not self.start(wait_live=False):
|
if not self.start(wait_live=False):
|
||||||
self._process = running
|
self._process = running
|
||||||
return False
|
return False
|
||||||
while datetime.now() < end_wait:
|
while datetime.now(timezone.utc) < end_wait:
|
||||||
try:
|
try:
|
||||||
self._log("debug", f"waiting for h2o({running.pid}) to exit.")
|
self._log("debug", f"waiting for h2o({running.pid}) to exit.")
|
||||||
running.wait(1)
|
running.wait(1)
|
||||||
|
|
@ -199,7 +199,7 @@ class H2o:
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
self._log("warning", f"h2o({running.pid}), not shut down yet.")
|
self._log("warning", f"h2o({running.pid}), not shut down yet.")
|
||||||
os.kill(running.pid, signal.SIGQUIT)
|
os.kill(running.pid, signal.SIGQUIT)
|
||||||
if not exited and datetime.now() >= end_wait:
|
if not exited and datetime.now(timezone.utc) >= end_wait:
|
||||||
self._log("error", f"h2o({running.pid}), terminate forcefully.")
|
self._log("error", f"h2o({running.pid}), terminate forcefully.")
|
||||||
os.kill(running.pid, signal.SIGKILL)
|
os.kill(running.pid, signal.SIGKILL)
|
||||||
running.terminate()
|
running.terminate()
|
||||||
|
|
@ -215,10 +215,10 @@ class H2o:
|
||||||
log_prefix: str = "h2o",
|
log_prefix: str = "h2o",
|
||||||
):
|
):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
if url is None:
|
if url is None:
|
||||||
url = f"https://{self._domain}:{self._port}/"
|
url = f"https://{self._domain}:{self._port}/"
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
if live:
|
if live:
|
||||||
r = curl.http_get(
|
r = curl.http_get(
|
||||||
url=url, extra_args=["--trace", "curl.trace", "--trace-time"]
|
url=url, extra_args=["--trace", "curl.trace", "--trace-time"]
|
||||||
|
|
@ -245,7 +245,7 @@ class H2o:
|
||||||
class H2oServer(H2o):
|
class H2oServer(H2o):
|
||||||
"""h2o HTTP/3 server for testing."""
|
"""h2o HTTP/3 server for testing."""
|
||||||
|
|
||||||
PORT_SPECS = {
|
PORT_SPECS: ClassVar[Dict[str, int]] = {
|
||||||
"h2o_https": socket.SOCK_STREAM,
|
"h2o_https": socket.SOCK_STREAM,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,10 +422,10 @@ error-log: {self._error_log}
|
||||||
log_prefix: str = "h2o",
|
log_prefix: str = "h2o",
|
||||||
):
|
):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
if url is None:
|
if url is None:
|
||||||
url = f"https://{self.env.proxy_domain}:{self._port}/"
|
url = f"https://{self.env.proxy_domain}:{self._port}/"
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
if live:
|
if live:
|
||||||
r = curl.http_get(
|
r = curl.http_get(
|
||||||
url=url, extra_args=["--trace", "curl.trace", "--trace-time"]
|
url=url, extra_args=["--trace", "curl.trace", "--trace-time"]
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from json import JSONEncoder
|
from json import JSONEncoder
|
||||||
from typing import Dict, List, Optional, Union
|
from typing import ClassVar, Dict, List, Optional, Union
|
||||||
|
|
||||||
from .curl import CurlClient, ExecResult
|
from .curl import CurlClient, ExecResult
|
||||||
from .env import Env, EnvError
|
from .env import Env, EnvError
|
||||||
|
|
@ -44,7 +44,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Httpd:
|
class Httpd:
|
||||||
|
|
||||||
MODULES = [
|
MODULES: ClassVar[List[str]] = [
|
||||||
'log_config', 'logio', 'unixd', 'version', 'watchdog',
|
'log_config', 'logio', 'unixd', 'version', 'watchdog',
|
||||||
'authn_core', 'authn_file',
|
'authn_core', 'authn_file',
|
||||||
'authz_user', 'authz_core', 'authz_host',
|
'authz_user', 'authz_core', 'authz_host',
|
||||||
|
|
@ -55,14 +55,14 @@ class Httpd:
|
||||||
'brotli',
|
'brotli',
|
||||||
'mpm_event',
|
'mpm_event',
|
||||||
]
|
]
|
||||||
COMMON_MODULES_DIRS = [
|
COMMON_MODULES_DIRS: ClassVar[List[str]] = [
|
||||||
'/usr/lib/apache2/modules', # debian
|
'/usr/lib/apache2/modules', # debian
|
||||||
'/usr/libexec/apache2/', # macos
|
'/usr/libexec/apache2/', # macos
|
||||||
]
|
]
|
||||||
|
|
||||||
MOD_CURLTEST = None
|
MOD_CURLTEST = None
|
||||||
|
|
||||||
PORT_SPECS = {
|
PORT_SPECS: ClassVar[Dict[str, int]] = {
|
||||||
'http': socket.SOCK_STREAM,
|
'http': socket.SOCK_STREAM,
|
||||||
'https': socket.SOCK_STREAM,
|
'https': socket.SOCK_STREAM,
|
||||||
'https-tcp-only': socket.SOCK_STREAM,
|
'https-tcp-only': socket.SOCK_STREAM,
|
||||||
|
|
@ -141,11 +141,11 @@ class Httpd:
|
||||||
p = subprocess.run(args, capture_output=True, cwd=self.env.gen_dir,
|
p = subprocess.run(args, capture_output=True, cwd=self.env.gen_dir,
|
||||||
input=intext.encode() if intext else None,
|
input=intext.encode() if intext else None,
|
||||||
env=env, check=True)
|
env=env, check=True)
|
||||||
start = datetime.now()
|
start = datetime.now(timezone.utc)
|
||||||
return ExecResult(args=args, exit_code=p.returncode,
|
return ExecResult(args=args, exit_code=p.returncode,
|
||||||
stdout=p.stdout.decode().splitlines(),
|
stdout=p.stdout.decode().splitlines(),
|
||||||
stderr=p.stderr.decode().splitlines(),
|
stderr=p.stderr.decode().splitlines(),
|
||||||
duration=datetime.now() - start)
|
duration=datetime.now(timezone.utc) - start)
|
||||||
|
|
||||||
def _cmd_httpd(self, cmd: str):
|
def _cmd_httpd(self, cmd: str):
|
||||||
args = [self.env.httpd,
|
args = [self.env.httpd,
|
||||||
|
|
@ -221,8 +221,8 @@ class Httpd:
|
||||||
|
|
||||||
def wait_dead(self, timeout: timedelta):
|
def wait_dead(self, timeout: timedelta):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
r = curl.http_get(url=f'http://{self.env.domain1}:{self.ports["http"]}/')
|
r = curl.http_get(url=f'http://{self.env.domain1}:{self.ports["http"]}/')
|
||||||
if r.exit_code != 0:
|
if r.exit_code != 0:
|
||||||
self._maybe_running = False
|
self._maybe_running = False
|
||||||
|
|
@ -234,8 +234,8 @@ class Httpd:
|
||||||
def wait_live(self, timeout: timedelta):
|
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())
|
timeout=timeout.total_seconds())
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
r = curl.http_get(url=f'http://{self.env.domain1}:{self.ports["http"]}/')
|
r = curl.http_get(url=f'http://{self.env.domain1}:{self.ports["http"]}/')
|
||||||
if r.exit_code == 0:
|
if r.exit_code == 0:
|
||||||
self._maybe_running = True
|
self._maybe_running = True
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict, Optional
|
from typing import ClassVar, Dict, Optional
|
||||||
|
|
||||||
from .curl import CurlClient
|
from .curl import CurlClient
|
||||||
from .env import Env, NghttpxUtil
|
from .env import Env, NghttpxUtil
|
||||||
|
|
@ -135,11 +135,11 @@ class Nghttpx:
|
||||||
running = self._process
|
running = self._process
|
||||||
self._process = None
|
self._process = None
|
||||||
os.kill(running.pid, signal.SIGQUIT)
|
os.kill(running.pid, signal.SIGQUIT)
|
||||||
end_wait = datetime.now() + timedelta(seconds=5)
|
end_wait = datetime.now(timezone.utc) + timedelta(seconds=5)
|
||||||
if not self.start(wait_live=False):
|
if not self.start(wait_live=False):
|
||||||
self._process = running
|
self._process = running
|
||||||
return False
|
return False
|
||||||
while datetime.now() < end_wait:
|
while datetime.now(timezone.utc) < end_wait:
|
||||||
try:
|
try:
|
||||||
log.debug(f'waiting for nghttpx({running.pid}) to exit.')
|
log.debug(f'waiting for nghttpx({running.pid}) to exit.')
|
||||||
running.wait(1)
|
running.wait(1)
|
||||||
|
|
@ -149,7 +149,7 @@ class Nghttpx:
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
log.warning(f'nghttpx({running.pid}), not shut down yet.')
|
log.warning(f'nghttpx({running.pid}), not shut down yet.')
|
||||||
os.kill(running.pid, signal.SIGQUIT)
|
os.kill(running.pid, signal.SIGQUIT)
|
||||||
if running and datetime.now() >= end_wait:
|
if running and datetime.now(timezone.utc) >= end_wait:
|
||||||
log.error(f'nghttpx({running.pid}), terminate forcefully.')
|
log.error(f'nghttpx({running.pid}), terminate forcefully.')
|
||||||
os.kill(running.pid, signal.SIGKILL)
|
os.kill(running.pid, signal.SIGKILL)
|
||||||
running.terminate()
|
running.terminate()
|
||||||
|
|
@ -159,8 +159,8 @@ class Nghttpx:
|
||||||
|
|
||||||
def wait_dead(self, timeout: timedelta):
|
def wait_dead(self, timeout: timedelta):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
xargs = [
|
xargs = [
|
||||||
'--trace', 'curl.trace', '--trace-time',
|
'--trace', 'curl.trace', '--trace-time',
|
||||||
'--connect-timeout', '1'
|
'--connect-timeout', '1'
|
||||||
|
|
@ -178,8 +178,8 @@ class Nghttpx:
|
||||||
|
|
||||||
def wait_live(self, timeout: timedelta):
|
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)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
xargs = [
|
xargs = [
|
||||||
'--trace', 'curl.trace', '--trace-time',
|
'--trace', 'curl.trace', '--trace-time',
|
||||||
'--connect-timeout', '1'
|
'--connect-timeout', '1'
|
||||||
|
|
@ -212,7 +212,7 @@ class Nghttpx:
|
||||||
|
|
||||||
class NghttpxQuic(Nghttpx):
|
class NghttpxQuic(Nghttpx):
|
||||||
|
|
||||||
PORT_SPECS = {
|
PORT_SPECS: ClassVar[Dict[str, int]] = {
|
||||||
'nghttpx_https': socket.SOCK_STREAM,
|
'nghttpx_https': socket.SOCK_STREAM,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,8 +327,8 @@ class NghttpxFwd(Nghttpx):
|
||||||
|
|
||||||
def wait_dead(self, timeout: timedelta):
|
def wait_dead(self, timeout: timedelta):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'https://{self.env.proxy_domain}:{self._port}/'
|
check_url = f'https://{self.env.proxy_domain}:{self._port}/'
|
||||||
r = curl.http_get(url=check_url)
|
r = curl.http_get(url=check_url)
|
||||||
if r.exit_code != 0:
|
if r.exit_code != 0:
|
||||||
|
|
@ -340,8 +340,8 @@ class NghttpxFwd(Nghttpx):
|
||||||
|
|
||||||
def wait_live(self, timeout: timedelta):
|
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)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'https://{self.env.proxy_domain}:{self._port}/'
|
check_url = f'https://{self.env.proxy_domain}:{self._port}/'
|
||||||
r = curl.http_get(url=check_url, extra_args=[
|
r = curl.http_get(url=check_url, extra_args=[
|
||||||
'--trace', 'curl.trace', '--trace-time'
|
'--trace', 'curl.trace', '--trace-time'
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import socket
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from . import CurlClient
|
from . import CurlClient
|
||||||
|
|
@ -242,8 +242,8 @@ class Sshd:
|
||||||
def wait_live(self, timeout: timedelta):
|
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())
|
timeout=timeout.total_seconds())
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
r = curl.http_get(url=f'scp://{self.env.domain1}:{self._port}/{self.home_dir}/data',
|
r = curl.http_get(url=f'scp://{self.env.domain1}:{self._port}/{self.home_dir}/data',
|
||||||
extra_args=[
|
extra_args=[
|
||||||
'--insecure',
|
'--insecure',
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
from .curl import CurlClient, ExecResult
|
from .curl import CurlClient, ExecResult
|
||||||
|
|
@ -152,8 +152,8 @@ class VsFTPD:
|
||||||
|
|
||||||
def wait_dead(self, timeout: timedelta):
|
def wait_dead(self, timeout: timedelta):
|
||||||
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'{self._scheme}://{self.domain}:{self.port}/'
|
check_url = f'{self._scheme}://{self.domain}:{self.port}/'
|
||||||
r = curl.ftp_get(urls=[check_url], extra_args=['-v'])
|
r = curl.ftp_get(urls=[check_url], extra_args=['-v'])
|
||||||
if r.exit_code != 0:
|
if r.exit_code != 0:
|
||||||
|
|
@ -165,8 +165,8 @@ class VsFTPD:
|
||||||
|
|
||||||
def wait_live(self, timeout: timedelta):
|
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)
|
||||||
try_until = datetime.now() + timeout
|
try_until = datetime.now(timezone.utc) + timeout
|
||||||
while datetime.now() < try_until:
|
while datetime.now(timezone.utc) < try_until:
|
||||||
check_url = f'{self._scheme}://{self.domain}:{self.port}/'
|
check_url = f'{self._scheme}://{self.domain}:{self.port}/'
|
||||||
r = curl.ftp_get(urls=[check_url], extra_args=[
|
r = curl.ftp_get(urls=[check_url], extra_args=[
|
||||||
'--trace', 'curl-start.trace', '--trace-time'
|
'--trace', 'curl-start.trace', '--trace-time'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue