Code import - branch feature/SIENTIAPDE-1646
This commit is contained in:
124
e2e/pi_web_api_test_server.py
Normal file
124
e2e/pi_web_api_test_server.py
Normal file
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
In-process HTTP server emulating PI Web API streamsets/recorded responses for E2E tests.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import time
|
||||
from typing import Any, Literal
|
||||
|
||||
from pytest_httpserver import HTTPServer
|
||||
from werkzeug import Request
|
||||
from werkzeug.wrappers import Response
|
||||
|
||||
PIWebAPIMode = Literal['success', 'empty', 'error', 'timeout']
|
||||
STREAMSETS_RECORDED_PATH = '/streamsets/recorded'
|
||||
|
||||
|
||||
class PIWebAPITestServer:
|
||||
"""
|
||||
Thread-backed PI Web API stub using pytest-httpserver (real HTTP for pycurl clients).
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._httpserver = HTTPServer(host='127.0.0.1', port=0)
|
||||
self._mode: PIWebAPIMode = 'success'
|
||||
self._rows: list[dict[str, Any]] = []
|
||||
self._timeout_sleep_seconds = 60
|
||||
self.requests: list[Request] = []
|
||||
|
||||
@property
|
||||
def host(self) -> str:
|
||||
return self._httpserver.host
|
||||
|
||||
@property
|
||||
def port(self) -> int:
|
||||
return self._httpserver.port
|
||||
|
||||
@property
|
||||
def base_url(self) -> str:
|
||||
return f'http://{self.host}:{self.port}'
|
||||
|
||||
def start(self) -> None:
|
||||
"""Start the HTTP server and register the streamsets handler."""
|
||||
self._httpserver.start()
|
||||
self._register_handler()
|
||||
|
||||
def stop(self) -> None:
|
||||
"""Stop the HTTP server."""
|
||||
self._httpserver.stop()
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear recorded requests and reset mode to success with no rows."""
|
||||
self.requests.clear()
|
||||
self._mode = 'success'
|
||||
self._rows = []
|
||||
self._httpserver.clear()
|
||||
self._register_handler()
|
||||
|
||||
def set_mode(
|
||||
self,
|
||||
mode: PIWebAPIMode,
|
||||
rows: list[dict[str, Any]] | None = None,
|
||||
*,
|
||||
timeout_sleep_seconds: int = 60,
|
||||
) -> None:
|
||||
"""
|
||||
Configure the next responses from the stub server.
|
||||
|
||||
Args:
|
||||
- mode: Response mode (success, empty, error, timeout)
|
||||
- rows: Optional list of row dicts with keys name, webid, timestamp, value
|
||||
- timeout_sleep_seconds: Sleep duration for timeout mode (must exceed client timeout)
|
||||
"""
|
||||
self._mode = mode
|
||||
if rows is not None:
|
||||
self._rows = rows
|
||||
self._timeout_sleep_seconds = timeout_sleep_seconds
|
||||
self._register_handler()
|
||||
|
||||
def _register_handler(self) -> None:
|
||||
self._httpserver.expect_request(
|
||||
STREAMSETS_RECORDED_PATH,
|
||||
method='GET',
|
||||
).respond_with_handler(self._handle_streamsets_recorded)
|
||||
|
||||
def _handle_streamsets_recorded(self, request: Request):
|
||||
self.requests.append(request)
|
||||
|
||||
if self._mode == 'timeout':
|
||||
time.sleep(self._timeout_sleep_seconds)
|
||||
return self._json_response({'Items': []}, status=200)
|
||||
|
||||
if self._mode == 'error':
|
||||
return self._json_response({'error': 'internal'}, status=500)
|
||||
|
||||
if self._mode == 'empty' or not self._rows:
|
||||
return self._json_response({'Items': []}, status=200)
|
||||
|
||||
items_by_name: dict[str, list[dict[str, Any]]] = {}
|
||||
for row in self._rows:
|
||||
name = row['name']
|
||||
items_by_name.setdefault(name, []).append(
|
||||
{
|
||||
'Timestamp': row['timestamp'],
|
||||
'Value': row['value'],
|
||||
'Good': True,
|
||||
'Questionable': False,
|
||||
}
|
||||
)
|
||||
|
||||
items = [
|
||||
{'Name': name, 'Items': points}
|
||||
for name, points in items_by_name.items()
|
||||
]
|
||||
return self._json_response({'Items': items}, status=200)
|
||||
|
||||
@staticmethod
|
||||
def _json_response(payload: dict[str, Any], *, status: int) -> Response:
|
||||
return Response(
|
||||
json.dumps(payload),
|
||||
status=status,
|
||||
mimetype='application/json',
|
||||
)
|
||||
Reference in New Issue
Block a user