Skip to content

Commit

Permalink
tests: add missing timeouts
Browse files Browse the repository at this point in the history
Sometimes tests can hang unexpectedly, need to eliminate all
blocking calls.

Signed-off-by: Evgeniy Zayats <[email protected]>
  • Loading branch information
Evgeniy Zayats committed Oct 29, 2024
1 parent 139aa5a commit 75ecb38
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 18 deletions.
6 changes: 4 additions & 2 deletions neofs-testlib/neofs_testlib/env/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
ALLOCATED_PORTS_FILE,
ALLOCATED_PORTS_LOCK_FILE,
BINARY_DOWNLOADS_LOCK_FILE,
DEFAULT_OBJECT_OPERATION_TIMEOUT,
DEFAULT_REST_OPERATION_TIMEOUT,
get_assets_dir_path,
)

Expand Down Expand Up @@ -593,7 +595,7 @@ def is_port_in_use(port: str):
@staticmethod
def download_binary(repo: str, version: str, file: str, target: str):
download_url = f"https://github.com/{repo}/releases/download/{version}/{file}"
resp = requests.get(download_url)
resp = requests.get(download_url, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)
if not resp.ok:
raise AssertionError(
f"Can not download binary from url: {download_url}: {resp.status_code}/{resp.reason}/{resp.json()}"
Expand Down Expand Up @@ -1128,7 +1130,7 @@ def stop(self):
@retry(wait=wait_fixed(10), stop=stop_after_attempt(10), reraise=True)
def _wait_until_ready(self):
endpoint = f"https://{self.address}" if self.tls_enabled else f"http://{self.address}"
resp = requests.get(endpoint, verify=False)
resp = requests.get(endpoint, verify=False, timeout=DEFAULT_REST_OPERATION_TIMEOUT)
assert resp.status_code == 200

def _generate_config(self):
Expand Down
14 changes: 10 additions & 4 deletions neofs-testlib/neofs_testlib/shell/local_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pexpect

from neofs_testlib.defaults import Options
from neofs_testlib.reporter import get_reporter
from neofs_testlib.shell.interfaces import CommandInspector, CommandOptions, CommandResult, Shell

Expand Down Expand Up @@ -37,7 +38,9 @@ def _exec_interactive(self, command: str, options: CommandOptions) -> CommandRes
log_file = tempfile.TemporaryFile() # File is reliable cross-platform way to capture output

try:
command_process = pexpect.spawn(command, timeout=options.timeout)
command_process = pexpect.spawn(
command, timeout=options.timeout if options.timeout else Options.get_default_shell_timeout()
)
except (pexpect.ExceptionPexpect, OSError) as exc:
raise RuntimeError(f"Command: {command}") from exc

Expand All @@ -46,7 +49,10 @@ def _exec_interactive(self, command: str, options: CommandOptions) -> CommandRes

try:
for interactive_input in options.interactive_inputs:
command_process.expect(interactive_input.prompt_pattern)
command_process.expect(
interactive_input.prompt_pattern,
timeout=options.timeout if options.timeout else Options.get_default_shell_timeout(),
)
command_process.sendline(interactive_input.input)
except (pexpect.ExceptionPexpect, OSError) as exc:
if options.check:
Expand All @@ -72,7 +78,7 @@ def _exec_non_interactive(self, command: str, options: CommandOptions) -> Comman
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
timeout=options.timeout,
timeout=options.timeout if options.timeout else Options.get_default_shell_timeout(),
shell=True,
)

Expand Down Expand Up @@ -104,7 +110,7 @@ def _get_pexpect_process_result(self, command_process: pexpect.spawn) -> Command
"""
# Wait for child process to end it's work
if command_process.isalive():
command_process.expect(pexpect.EOF)
command_process.expect(pexpect.EOF, timeout=Options.get_default_shell_timeout())

# Close the process to obtain the exit code
command_process.close()
Expand Down
6 changes: 3 additions & 3 deletions neofs-testlib/neofs_testlib_tests/pytest/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pytest
import requests
from botocore.config import Config

from helpers.common import DEFAULT_OBJECT_OPERATION_TIMEOUT, DEFAULT_REST_OPERATION_TIMEOUT
from neofs_testlib.env.env import NeoFSEnv, NodeWallet
from neofs_testlib.utils.wallet import get_last_public_key_from_wallet, init_wallet

Expand Down Expand Up @@ -171,7 +171,7 @@ def test_gateways_put_get(neofs_env: NeoFSEnv, wallet: NodeWallet, zero_fee, gw_
request = f"http://{neofs_env.rest_gw.address}/v1/upload/{cid}"
files = {"upload_file": open(filename, "rb")}
body = {"filename": filename}
resp = requests.post(request, files=files, data=body)
resp = requests.post(request, files=files, data=body, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand All @@ -189,7 +189,7 @@ def test_gateways_put_get(neofs_env: NeoFSEnv, wallet: NodeWallet, zero_fee, gw_
else:
request = f"http://{neofs_env.rest_gw.address}/v1/get/{cid}/{oid}{download_attribute}"

resp = requests.get(request, stream=True)
resp = requests.get(request, stream=True, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand Down
3 changes: 3 additions & 0 deletions pytest_tests/lib/helpers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
ALLOCATED_PORTS_FILE = "/tmp/allocated_ports.txt"
BINARY_DOWNLOADS_LOCK_FILE = "/tmp/binary_downloads.lock"

DEFAULT_OBJECT_OPERATION_TIMEOUT = 600
DEFAULT_REST_OPERATION_TIMEOUT = 10

# Generate wallet configs
# TODO: we should move all info about wallet configs to fixtures
WALLET_CONFIG = os.path.join(os.getcwd(), "wallet_config.yml")
Expand Down
25 changes: 17 additions & 8 deletions pytest_tests/lib/helpers/rest_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
import requests
from helpers.aws_cli_client import LONG_TIMEOUT
from helpers.cli_helpers import _cmd_run
from helpers.common import SIMPLE_OBJECT_SIZE, get_assets_dir_path
from helpers.common import (
DEFAULT_OBJECT_OPERATION_TIMEOUT,
DEFAULT_REST_OPERATION_TIMEOUT,
SIMPLE_OBJECT_SIZE,
get_assets_dir_path,
)
from helpers.complex_object_actions import get_nodes_without_object
from helpers.file_helper import get_file_hash
from helpers.neofs_verbs import get_object
Expand Down Expand Up @@ -51,7 +56,7 @@ def get_via_rest_gate(

if not skip_options_verify:
verify_options_request(request)
resp = requests.get(request, stream=True)
resp = requests.get(request, stream=True, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand Down Expand Up @@ -81,7 +86,7 @@ def get_via_zip_http_gate(cid: str, prefix: str, endpoint: str):
endpoint: http gate endpoint
"""
request = f"{endpoint}/zip/{cid}/{prefix}"
resp = requests.get(request, stream=True)
resp = requests.get(request, stream=True, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand Down Expand Up @@ -125,7 +130,7 @@ def get_via_rest_gate_by_attribute(

if not skip_options_verify:
verify_options_request(request)
resp = requests.get(request, stream=True)
resp = requests.get(request, stream=True, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand Down Expand Up @@ -169,7 +174,9 @@ def upload_via_rest_gate(
files = {"upload_file": (path, open(path, "rb"), file_content_type)}
body = {"filename": path}
verify_options_request(request)
resp = requests.post(request, files=files, data=body, headers=headers, cookies=cookies)
resp = requests.post(
request, files=files, data=body, headers=headers, cookies=cookies, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT
)

if not resp.ok:
if error_pattern:
Expand Down Expand Up @@ -394,7 +401,9 @@ def new_upload_via_rest_gate(
headers["Content-Type"] = file_content_type

verify_options_request(request)
resp = requests.post(request, data=file_content, headers=headers, cookies=cookies)
resp = requests.post(
request, data=file_content, headers=headers, cookies=cookies, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT
)

if not resp.ok:
if error_pattern:
Expand Down Expand Up @@ -431,7 +440,7 @@ def get_epoch_duration_via_rest_gate(endpoint: str) -> int:
request = f"{endpoint}/network-info"

verify_options_request(request)
resp = requests.get(request, stream=True)
resp = requests.get(request, stream=True, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT)

if not resp.ok:
raise Exception(
Expand All @@ -449,7 +458,7 @@ def get_epoch_duration_via_rest_gate(endpoint: str) -> int:


def verify_options_request(request):
options_resp = requests.options(request)
options_resp = requests.options(request, timeout=DEFAULT_REST_OPERATION_TIMEOUT)
assert options_resp.status_code == 200, "Invalid status code for OPTIONS request"
for cors_header in ("Access-Control-Allow-Headers", "Access-Control-Allow-Methods", "Access-Control-Allow-Origin"):
assert cors_header in options_resp.headers, f"Not CORS header {cors_header} in OPTIONS response"
Expand Down
5 changes: 4 additions & 1 deletion pytest_tests/tests/services/rest_gate/test_rest_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import allure
import pytest
import requests
from helpers.common import DEFAULT_OBJECT_OPERATION_TIMEOUT
from helpers.container import create_container
from helpers.file_helper import generate_file
from helpers.wellknown_acl import PUBLIC_ACL
Expand Down Expand Up @@ -56,7 +57,9 @@ def test_object_can_be_put_get_by_streaming(self, object_size: int, gw_endpoint)
with allure.step("Put objects and Get object and verify hashes [ get/$CID/$OID ]"):
# https://docs.python-requests.org/en/latest/user/advanced/#streaming-uploads
with open(file_path, "rb") as file:
resp = requests.post(f"{gw_endpoint}/objects/{cid}", data=file)
resp = requests.post(
f"{gw_endpoint}/objects/{cid}", data=file, timeout=DEFAULT_OBJECT_OPERATION_TIMEOUT
)

if not resp.ok:
raise Exception(
Expand Down

0 comments on commit 75ecb38

Please sign in to comment.