From bfb0d9007269f8d5dbd89f80543a34d18951100e Mon Sep 17 00:00:00 2001 From: Sandip Pandey Date: Thu, 25 Jan 2024 17:17:07 +0100 Subject: [PATCH 1/2] Fix Application tester re-run failure --- scripts/application_tester/main.py | 1 + .../tribler_apptester/executor.py | 24 ++++++++- .../tribler_apptester/tests/__init__.py | 0 .../tribler_apptester/tests/test_executor.py | 53 +++++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 scripts/application_tester/tribler_apptester/tests/__init__.py create mode 100644 scripts/application_tester/tribler_apptester/tests/test_executor.py diff --git a/scripts/application_tester/main.py b/scripts/application_tester/main.py index 936d88006d6..cd1c8bc31f0 100644 --- a/scripts/application_tester/main.py +++ b/scripts/application_tester/main.py @@ -48,6 +48,7 @@ executor_kwargs['check_process_started_interval'] = 1 executor = Executor(args, **executor_kwargs) + executor.set_core_api_port() loop = get_event_loop() coro = executor.start() diff --git a/scripts/application_tester/tribler_apptester/executor.py b/scripts/application_tester/tribler_apptester/executor.py index 906483f1802..f853690bede 100644 --- a/scripts/application_tester/tribler_apptester/executor.py +++ b/scripts/application_tester/tribler_apptester/executor.py @@ -15,6 +15,7 @@ from typing import Dict, Optional from tribler.core.config.tribler_config import TriblerConfig +from tribler.core.utilities.network_utils import default_network_utils, FreePortNotFoundError from tribler_apptester.action_selector import ActionSelector from tribler_apptester.actions.shutdown_action import ShutdownAction from tribler_apptester.monitors.download_monitor import DownloadMonitor @@ -32,6 +33,8 @@ SHUTDOWN_TIMEOUT = 30 +DEFAULT_CORE_API_PORT = 20100 + class Executor(object): @@ -42,7 +45,7 @@ def __init__(self, args, read_config_delay=2, read_config_attempts=10, check_pro self.check_process_started_interval = check_process_started_interval self.read_config_attempts = read_config_attempts self.code_port = args.codeport - self.api_port = int(os.environ.get('CORE_API_PORT')) + self.api_port = None self._logger = logging.getLogger(self.__class__.__name__) self.allow_plain_downloads = args.plain self.pending_tasks: Dict[bytes, Future] = {} # Dictionary of pending tasks @@ -65,6 +68,25 @@ def __init__(self, args, read_config_delay=2, read_config_attempts=10, check_pro self.request_manager = None self.action_selector = ActionSelector() + def set_core_api_port(self) -> None: + """ + Set the core API port to a free port. + Prefer the port specified in the environment variable CORE_API_PORT. + Then update the environment variable CORE_API_PORT to match the port that was chosen. + """ + base_api_port = int(os.environ.get('CORE_API_PORT', f"{DEFAULT_CORE_API_PORT}")) + + try: + self.api_port = default_network_utils.get_first_free_port(start=base_api_port) + self._logger.info(f"Setting the Core API port to {self.api_port}") + except FreePortNotFoundError: + self._logger.error("Could not find a free port to use as Core API port.") + raise + + # Update the environment variable CORE_API_PORT to the port that was chosen + # so that the Tribler process can use the correct port. + os.environ['CORE_API_PORT'] = str(self.api_port) + async def start(self): await self.start_tribler() diff --git a/scripts/application_tester/tribler_apptester/tests/__init__.py b/scripts/application_tester/tribler_apptester/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/scripts/application_tester/tribler_apptester/tests/test_executor.py b/scripts/application_tester/tribler_apptester/tests/test_executor.py new file mode 100644 index 00000000000..846e187f178 --- /dev/null +++ b/scripts/application_tester/tribler_apptester/tests/test_executor.py @@ -0,0 +1,53 @@ +import argparse +import os +import random +from unittest.mock import MagicMock, patch + +import pytest + +from tribler.core.utilities.network_utils import FreePortNotFoundError +from tribler_apptester.executor import Executor, DEFAULT_CORE_API_PORT + + +@pytest.fixture(name='executor') +def fixture_executor() -> Executor: + args = argparse.Namespace( + tribler_executable='python ./src/run_tribler.py', + plain=False, + duration=120, + silent=False, + codeport=5500, + monitordownloads=None, + monitorresources=None, + monitoripv8=None, + fragile=True + ) + return Executor(args) + + +@patch('os.environ', new={}) +@patch('tribler.core.utilities.network_utils.default_network_utils.get_first_free_port') +@pytest.mark.parametrize("initial_core_api_port", [DEFAULT_CORE_API_PORT, 8085]) +def test_set_core_api_port_(mock_get_first_free_port: MagicMock, executor: Executor, initial_core_api_port): + assert executor.api_port is None + + os.environ['CORE_API_PORT'] = str(initial_core_api_port) + next_available_free_port = initial_core_api_port + random.randint(0, 100) + mock_get_first_free_port.return_value = next_available_free_port + + executor.set_core_api_port() + + assert os.environ.get('CORE_API_PORT') == str(next_available_free_port) + assert executor.api_port == next_available_free_port + + +@patch('os.environ', new={}) +@patch('tribler.core.utilities.network_utils.default_network_utils.get_first_free_port') +def test_set_core_api_port_not_found(mock_get_first_free_port: MagicMock, executor: Executor): + assert executor.api_port is None + + os.environ['CORE_API_PORT'] = str(DEFAULT_CORE_API_PORT) + mock_get_first_free_port.side_effect = FreePortNotFoundError('Free port not found') + + with pytest.raises(FreePortNotFoundError): + executor.set_core_api_port() From 66096483dec51147fc2fb494386a48c6a45a9dfb Mon Sep 17 00:00:00 2001 From: Sandip Pandey Date: Fri, 26 Jan 2024 12:06:25 +0100 Subject: [PATCH 2/2] Fix imports --- .../application_tester/tribler_apptester/tests/test_executor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/application_tester/tribler_apptester/tests/test_executor.py b/scripts/application_tester/tribler_apptester/tests/test_executor.py index 846e187f178..0fbc0410745 100644 --- a/scripts/application_tester/tribler_apptester/tests/test_executor.py +++ b/scripts/application_tester/tribler_apptester/tests/test_executor.py @@ -5,8 +5,8 @@ import pytest +from tribler_apptester.executor import DEFAULT_CORE_API_PORT, Executor from tribler.core.utilities.network_utils import FreePortNotFoundError -from tribler_apptester.executor import Executor, DEFAULT_CORE_API_PORT @pytest.fixture(name='executor')