Fix some tests

This commit is contained in:
Matthias 2020-12-27 10:56:19 +01:00
parent 9f873305eb
commit 54a50b1fb4
4 changed files with 51 additions and 33 deletions

View File

@ -10,6 +10,9 @@ class UvicornServer(uvicorn.Server):
Multithreaded server - as found in https://github.com/encode/uvicorn/issues/742
"""
def install_signal_handlers(self):
"""
In the parent implementation, this starts the thread, therefore we must patch it away here.
"""
pass
@contextlib.contextmanager

View File

@ -1,4 +1,5 @@
import logging
from ipaddress import IPv4Address
from typing import Any, Dict, Optional
import uvicorn
@ -16,7 +17,7 @@ logger = logging.getLogger(__name__)
class ApiServer(RPCHandler):
_rpc: Optional[RPC] = None
_rpc: RPC = None
_config: Dict[str, Any] = {}
def __init__(self, rpc: RPC, config: Dict[str, Any]) -> None:
@ -34,6 +35,7 @@ class ApiServer(RPCHandler):
def cleanup(self) -> None:
""" Cleanup pending module resources """
if self._server:
logger.info("Stopping API Server")
self._server.cleanup()
def send_msg(self, msg: Dict[str, str]) -> None:
@ -71,11 +73,26 @@ class ApiServer(RPCHandler):
"""
Start API ... should be run in thread.
"""
uvconfig = uvicorn.Config(self.app,
port=self._config['api_server'].get('listen_port', 8080),
host=self._config['api_server'].get(
'listen_ip_address', '127.0.0.1'),
access_log=True)
self._server = UvicornServer(uvconfig)
rest_ip = self._config['api_server']['listen_ip_address']
rest_port = self._config['api_server']['listen_port']
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.")

View File

@ -5,17 +5,18 @@ Unit test file for rpc/api_server.py
from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest.mock import ANY, MagicMock, PropertyMock
from fastapi.applications import FastAPI
import pytest
from fastapi.testclient import TestClient
from flask import Flask
from fastapi import FastAPI
from requests.auth import _basic_auth_str
from freqtrade.__init__ import __version__
from freqtrade.loggers import setup_logging, setup_logging_pre
from freqtrade.persistence import PairLocks, Trade
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.state import RunMode, State
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",
}})
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
mocker.patch('freqtrade.rpc.api_server.threading.Thread', 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)
assert apiserver._config == default_conf
apiserver.run()
assert server_mock.call_count == 1
assert server_mock.call_args_list[0][0][0] == "127.0.0.1"
assert server_mock.call_args_list[0][0][1] == 8080
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
assert hasattr(apiserver, "srv")
assert apiserver._config == default_conf
apiserver.start_api()
assert server_mock.call_count == 2
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 Local Rest Server.", caplog)
@ -217,12 +217,12 @@ def test_api_run(default_conf, mocker, caplog):
"listen_port": 8089,
"password": "",
}})
apiserver.run()
apiserver.start_api()
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][1] == 8089
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
assert server_mock.call_args_list[0][0][0].host == "0.0.0.0"
assert server_mock.call_args_list[0][0][0].port == 8089
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 Local Rest Server.", caplog)
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
caplog.clear()
mocker.patch('freqtrade.rpc.api_server.make_server', MagicMock(side_effect=Exception))
apiserver.run()
mocker.patch('freqtrade.rpc.api_server2.webserver.UvicornServer', MagicMock(side_effect=Exception))
apiserver.start_api()
assert log_has("Api server failed to start.", caplog)
@ -247,17 +247,15 @@ def test_api_cleanup(default_conf, mocker, caplog):
"password": "testPass",
}})
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.run_api()
stop_mock = MagicMock()
stop_mock.shutdown = MagicMock()
apiserver.srv = stop_mock
apiserver.cleanup()
assert stop_mock.shutdown.call_count == 1
assert apiserver._server.cleanup.call_count == 1
assert log_has("Stopping API Server", caplog)

View File

@ -160,7 +160,7 @@ def test_startupmessages_telegram_enabled(mocker, default_conf, caplog) -> None:
def test_init_apiserver_disabled(mocker, default_conf, caplog) -> None:
caplog.set_level(logging.DEBUG)
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
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:
caplog.set_level(logging.DEBUG)
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["api_server"] = {"enabled": True,