Fix some tests
This commit is contained in:
parent
9f873305eb
commit
54a50b1fb4
@ -10,6 +10,9 @@ class UvicornServer(uvicorn.Server):
|
|||||||
Multithreaded server - as found in https://github.com/encode/uvicorn/issues/742
|
Multithreaded server - as found in https://github.com/encode/uvicorn/issues/742
|
||||||
"""
|
"""
|
||||||
def install_signal_handlers(self):
|
def install_signal_handlers(self):
|
||||||
|
"""
|
||||||
|
In the parent implementation, this starts the thread, therefore we must patch it away here.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from ipaddress import IPv4Address
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
@ -16,7 +17,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class ApiServer(RPCHandler):
|
class ApiServer(RPCHandler):
|
||||||
|
|
||||||
_rpc: Optional[RPC] = None
|
_rpc: RPC = None
|
||||||
_config: Dict[str, Any] = {}
|
_config: Dict[str, Any] = {}
|
||||||
|
|
||||||
def __init__(self, rpc: RPC, config: Dict[str, Any]) -> None:
|
def __init__(self, rpc: RPC, config: Dict[str, Any]) -> None:
|
||||||
@ -34,6 +35,7 @@ class ApiServer(RPCHandler):
|
|||||||
def cleanup(self) -> None:
|
def cleanup(self) -> None:
|
||||||
""" Cleanup pending module resources """
|
""" Cleanup pending module resources """
|
||||||
if self._server:
|
if self._server:
|
||||||
|
logger.info("Stopping API Server")
|
||||||
self._server.cleanup()
|
self._server.cleanup()
|
||||||
|
|
||||||
def send_msg(self, msg: Dict[str, str]) -> None:
|
def send_msg(self, msg: Dict[str, str]) -> None:
|
||||||
@ -71,11 +73,26 @@ class ApiServer(RPCHandler):
|
|||||||
"""
|
"""
|
||||||
Start API ... should be run in thread.
|
Start API ... should be run in thread.
|
||||||
"""
|
"""
|
||||||
uvconfig = uvicorn.Config(self.app,
|
rest_ip = self._config['api_server']['listen_ip_address']
|
||||||
port=self._config['api_server'].get('listen_port', 8080),
|
rest_port = self._config['api_server']['listen_port']
|
||||||
host=self._config['api_server'].get(
|
|
||||||
'listen_ip_address', '127.0.0.1'),
|
|
||||||
access_log=True)
|
|
||||||
self._server = UvicornServer(uvconfig)
|
|
||||||
|
|
||||||
self._server.run_in_thread()
|
logger.info(f'Starting HTTP Server at {rest_ip}:{rest_port}')
|
||||||
|
if not IPv4Address(rest_ip).is_loopback:
|
||||||
|
logger.warning("SECURITY WARNING - Local Rest Server listening to external connections")
|
||||||
|
logger.warning("SECURITY WARNING - This is insecure please set to your loopback,"
|
||||||
|
"e.g 127.0.0.1 in config.json")
|
||||||
|
|
||||||
|
if not self._config['api_server'].get('password'):
|
||||||
|
logger.warning("SECURITY WARNING - No password for local REST Server defined. "
|
||||||
|
"Please make sure that this is intentional!")
|
||||||
|
|
||||||
|
logger.info('Starting Local Rest Server.')
|
||||||
|
uvconfig = uvicorn.Config(self.app,
|
||||||
|
port=rest_port,
|
||||||
|
host=rest_ip,
|
||||||
|
access_log=True)
|
||||||
|
try:
|
||||||
|
self._server = UvicornServer(uvconfig)
|
||||||
|
self._server.run_in_thread()
|
||||||
|
except Exception:
|
||||||
|
logger.exception("Api server failed to start.")
|
||||||
|
@ -5,17 +5,18 @@ Unit test file for rpc/api_server.py
|
|||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import ANY, MagicMock, PropertyMock
|
from unittest.mock import ANY, MagicMock, PropertyMock
|
||||||
|
from fastapi.applications import FastAPI
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from flask import Flask
|
from fastapi import FastAPI
|
||||||
from requests.auth import _basic_auth_str
|
from requests.auth import _basic_auth_str
|
||||||
|
|
||||||
from freqtrade.__init__ import __version__
|
from freqtrade.__init__ import __version__
|
||||||
from freqtrade.loggers import setup_logging, setup_logging_pre
|
from freqtrade.loggers import setup_logging, setup_logging_pre
|
||||||
from freqtrade.persistence import PairLocks, Trade
|
from freqtrade.persistence import PairLocks, Trade
|
||||||
from freqtrade.rpc import RPC
|
from freqtrade.rpc import RPC
|
||||||
from freqtrade.rpc.api_server import BASE_URI # , ApiServer
|
from freqtrade.rpc.api_server111 import BASE_URI # , ApiServer
|
||||||
from freqtrade.rpc.api_server2 import ApiServer
|
from freqtrade.rpc.api_server2 import ApiServer
|
||||||
from freqtrade.state import RunMode, State
|
from freqtrade.state import RunMode, State
|
||||||
from tests.conftest import create_mock_trades, get_patched_freqtradebot, log_has, patch_get_signal
|
from tests.conftest import create_mock_trades, get_patched_freqtradebot, log_has, patch_get_signal
|
||||||
@ -191,20 +192,19 @@ def test_api_run(default_conf, mocker, caplog):
|
|||||||
"password": "testPass",
|
"password": "testPass",
|
||||||
}})
|
}})
|
||||||
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
||||||
mocker.patch('freqtrade.rpc.api_server.threading.Thread', MagicMock())
|
|
||||||
|
|
||||||
server_mock = MagicMock()
|
server_mock = MagicMock()
|
||||||
mocker.patch('freqtrade.rpc.api_server.make_server', server_mock)
|
mocker.patch('freqtrade.rpc.api_server2.webserver.UvicornServer', server_mock)
|
||||||
|
|
||||||
apiserver = ApiServer(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
apiserver = ApiServer(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||||
|
|
||||||
assert apiserver._config == default_conf
|
|
||||||
apiserver.run()
|
|
||||||
assert server_mock.call_count == 1
|
assert server_mock.call_count == 1
|
||||||
assert server_mock.call_args_list[0][0][0] == "127.0.0.1"
|
assert apiserver._config == default_conf
|
||||||
assert server_mock.call_args_list[0][0][1] == 8080
|
apiserver.start_api()
|
||||||
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
|
assert server_mock.call_count == 2
|
||||||
assert hasattr(apiserver, "srv")
|
assert server_mock.call_args_list[0][0][0].host == "127.0.0.1"
|
||||||
|
assert server_mock.call_args_list[0][0][0].port == 8080
|
||||||
|
assert isinstance(server_mock.call_args_list[0][0][0].app, FastAPI)
|
||||||
|
|
||||||
assert log_has("Starting HTTP Server at 127.0.0.1:8080", caplog)
|
assert log_has("Starting HTTP Server at 127.0.0.1:8080", caplog)
|
||||||
assert log_has("Starting Local Rest Server.", caplog)
|
assert log_has("Starting Local Rest Server.", caplog)
|
||||||
@ -217,12 +217,12 @@ def test_api_run(default_conf, mocker, caplog):
|
|||||||
"listen_port": 8089,
|
"listen_port": 8089,
|
||||||
"password": "",
|
"password": "",
|
||||||
}})
|
}})
|
||||||
apiserver.run()
|
apiserver.start_api()
|
||||||
|
|
||||||
assert server_mock.call_count == 1
|
assert server_mock.call_count == 1
|
||||||
assert server_mock.call_args_list[0][0][0] == "0.0.0.0"
|
assert server_mock.call_args_list[0][0][0].host == "0.0.0.0"
|
||||||
assert server_mock.call_args_list[0][0][1] == 8089
|
assert server_mock.call_args_list[0][0][0].port == 8089
|
||||||
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
|
assert isinstance(server_mock.call_args_list[0][0][0].app, FastAPI)
|
||||||
assert log_has("Starting HTTP Server at 0.0.0.0:8089", caplog)
|
assert log_has("Starting HTTP Server at 0.0.0.0:8089", caplog)
|
||||||
assert log_has("Starting Local Rest Server.", caplog)
|
assert log_has("Starting Local Rest Server.", caplog)
|
||||||
assert log_has("SECURITY WARNING - Local Rest Server listening to external connections",
|
assert log_has("SECURITY WARNING - Local Rest Server listening to external connections",
|
||||||
@ -234,8 +234,8 @@ def test_api_run(default_conf, mocker, caplog):
|
|||||||
|
|
||||||
# Test crashing flask
|
# Test crashing flask
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
mocker.patch('freqtrade.rpc.api_server.make_server', MagicMock(side_effect=Exception))
|
mocker.patch('freqtrade.rpc.api_server2.webserver.UvicornServer', MagicMock(side_effect=Exception))
|
||||||
apiserver.run()
|
apiserver.start_api()
|
||||||
assert log_has("Api server failed to start.", caplog)
|
assert log_has("Api server failed to start.", caplog)
|
||||||
|
|
||||||
|
|
||||||
@ -247,17 +247,15 @@ def test_api_cleanup(default_conf, mocker, caplog):
|
|||||||
"password": "testPass",
|
"password": "testPass",
|
||||||
}})
|
}})
|
||||||
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
||||||
mocker.patch('freqtrade.rpc.api_server.threading.Thread', MagicMock())
|
|
||||||
mocker.patch('freqtrade.rpc.api_server.make_server', MagicMock())
|
server_mock = MagicMock()
|
||||||
|
server_mock.cleanup = MagicMock()
|
||||||
|
mocker.patch('freqtrade.rpc.api_server2.webserver.UvicornServer', server_mock)
|
||||||
|
|
||||||
apiserver = ApiServer(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
apiserver = ApiServer(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||||
apiserver.run_api()
|
|
||||||
stop_mock = MagicMock()
|
|
||||||
stop_mock.shutdown = MagicMock()
|
|
||||||
apiserver.srv = stop_mock
|
|
||||||
|
|
||||||
apiserver.cleanup()
|
apiserver.cleanup()
|
||||||
assert stop_mock.shutdown.call_count == 1
|
assert apiserver._server.cleanup.call_count == 1
|
||||||
assert log_has("Stopping API Server", caplog)
|
assert log_has("Stopping API Server", caplog)
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ def test_startupmessages_telegram_enabled(mocker, default_conf, caplog) -> None:
|
|||||||
def test_init_apiserver_disabled(mocker, default_conf, caplog) -> None:
|
def test_init_apiserver_disabled(mocker, default_conf, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
run_mock = MagicMock()
|
run_mock = MagicMock()
|
||||||
mocker.patch('freqtrade.rpc.api_server.ApiServer.run', run_mock)
|
mocker.patch('freqtrade.rpc.api_server2.ApiServer.start_api', run_mock)
|
||||||
default_conf['telegram']['enabled'] = False
|
default_conf['telegram']['enabled'] = False
|
||||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ def test_init_apiserver_disabled(mocker, default_conf, caplog) -> None:
|
|||||||
def test_init_apiserver_enabled(mocker, default_conf, caplog) -> None:
|
def test_init_apiserver_enabled(mocker, default_conf, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
run_mock = MagicMock()
|
run_mock = MagicMock()
|
||||||
mocker.patch('freqtrade.rpc.api_server.ApiServer.run', run_mock)
|
mocker.patch('freqtrade.rpc.api_server2.ApiServer.start_api', run_mock)
|
||||||
|
|
||||||
default_conf["telegram"]["enabled"] = False
|
default_conf["telegram"]["enabled"] = False
|
||||||
default_conf["api_server"] = {"enabled": True,
|
default_conf["api_server"] = {"enabled": True,
|
||||||
|
Loading…
Reference in New Issue
Block a user