mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-13 09:31:56 +00:00
80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
"""EOS notifies ``ems.notify_url`` after a completed optimization."""
|
|||
|
|
|
||
|
|
import json
|
||
|
|
import threading
|
||
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from pydantic import ValidationError
|
||
|
|
|
||
|
|
from akkudoktoreos.core import ems as ems_module
|
||
|
|
from akkudoktoreos.core.emsettings import EnergyManagementCommonSettings
|
||
|
|
|
||
|
|
|
||
|
|
def _receiver():
|
||
|
|
received: list[dict] = []
|
||
|
|
|
||
|
|
class Handler(BaseHTTPRequestHandler):
|
||
|
|
def do_POST(self): # noqa: N802
|
||
|
|
length = int(self.headers.get("Content-Length", 0))
|
||
|
|
received.append(
|
||
|
|
{
|
||
|
|
"path": self.path,
|
||
|
|
"type": self.headers.get("Content-Type"),
|
||
|
|
"body": json.loads(self.rfile.read(length)),
|
||
|
|
}
|
||
|
|
)
|
||
|
|
self.send_response(204)
|
||
|
|
self.end_headers()
|
||
|
|
|
||
|
|
def log_message(self, *args):
|
||
|
|
pass
|
||
|
|
|
||
|
|
server = HTTPServer(("127.0.0.1", 0), Handler)
|
||
|
|
threading.Thread(target=server.serve_forever, daemon=True).start()
|
||
|
|
return server, received
|
||
|
|
|
||
|
|
|
||
|
|
def test_completed_optimization_is_posted():
|
||
|
|
server, received = _receiver()
|
||
|
|
try:
|
||
|
|
url = f"http://127.0.0.1:{server.server_port}/api/eos/solution-ready"
|
||
|
|
event = {"event": "optimization_completed", "duration_s": 12.5}
|
||
|
|
thread = ems_module.notify_optimization_completed(url, event)
|
||
|
|
assert thread is not None
|
||
|
|
thread.join(timeout=10)
|
||
|
|
assert received == [
|
||
|
|
{"path": "/api/eos/solution-ready", "type": "application/json", "body": event}
|
||
|
|
]
|
||
|
|
finally:
|
||
|
|
server.shutdown()
|
||
|
|
|
||
|
|
|
||
|
|
def test_no_url_no_notification():
|
||
|
|
assert ems_module.notify_optimization_completed(None, {"event": "x"}) is None
|
||
|
|
assert ems_module.notify_optimization_completed("", {"event": "x"}) is None
|
||
|
|
|
||
|
|
|
||
|
|
def test_unreachable_receiver_is_logged_once(monkeypatch):
|
||
|
|
warnings: list[str] = []
|
||
|
|
monkeypatch.setattr(ems_module.logger, "warning", lambda *a, **k: warnings.append(a[0]))
|
||
|
|
monkeypatch.setattr(ems_module, "_notify_failing", False)
|
||
|
|
server, _ = _receiver()
|
||
|
|
port = server.server_port
|
||
|
|
server.shutdown()
|
||
|
|
server.server_close()
|
||
|
|
for _ in range(3):
|
||
|
|
ems_module._post_notification(f"http://127.0.0.1:{port}/x", {"event": "x"})
|
||
|
|
assert len(warnings) == 1
|
||
|
|
|
||
|
|
|
||
|
|
def test_notify_url_setting():
|
||
|
|
assert EnergyManagementCommonSettings().notify_url is None
|
||
|
|
assert EnergyManagementCommonSettings(notify_url=" ").notify_url is None
|
||
|
|
assert (
|
||
|
|
EnergyManagementCommonSettings(notify_url=" http://127.0.0.1:8080/a ").notify_url
|
||
|
|
== "http://127.0.0.1:8080/a"
|
||
|
|
)
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
EnergyManagementCommonSettings(notify_url="file:///etc/passwd")
|