piphi-runtime-testkit-python 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- piphi_runtime_testkit_python/__init__.py +9 -2
- piphi_runtime_testkit_python/builders.py +39 -0
- piphi_runtime_testkit_python/mock_core.py +37 -0
- {piphi_runtime_testkit_python-0.1.1.dist-info → piphi_runtime_testkit_python-0.1.2.dist-info}/METADATA +1 -1
- piphi_runtime_testkit_python-0.1.2.dist-info/RECORD +10 -0
- piphi_runtime_testkit_python-0.1.1.dist-info/RECORD +0 -10
- {piphi_runtime_testkit_python-0.1.1.dist-info → piphi_runtime_testkit_python-0.1.2.dist-info}/WHEEL +0 -0
- {piphi_runtime_testkit_python-0.1.1.dist-info → piphi_runtime_testkit_python-0.1.2.dist-info}/entry_points.txt +0 -0
- {piphi_runtime_testkit_python-0.1.1.dist-info → piphi_runtime_testkit_python-0.1.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
"""Pytest-first helpers for testing PiPhi runtime integrations."""
|
|
2
2
|
|
|
3
3
|
from .assertions import assert_entities_response, assert_event_sent, assert_telemetry_sent
|
|
4
|
-
from .builders import
|
|
5
|
-
|
|
4
|
+
from .builders import (
|
|
5
|
+
build_config_payload,
|
|
6
|
+
build_config_snapshot,
|
|
7
|
+
build_core_config_row,
|
|
8
|
+
build_runtime_headers,
|
|
9
|
+
)
|
|
10
|
+
from .mock_core import CapturedRequest, MockCoreServer, RUNTIME_CONFIG_FETCH_PATH
|
|
6
11
|
|
|
7
12
|
__all__ = [
|
|
8
13
|
"CapturedRequest",
|
|
9
14
|
"MockCoreServer",
|
|
15
|
+
"RUNTIME_CONFIG_FETCH_PATH",
|
|
10
16
|
"assert_entities_response",
|
|
11
17
|
"assert_event_sent",
|
|
12
18
|
"assert_telemetry_sent",
|
|
13
19
|
"build_config_payload",
|
|
14
20
|
"build_config_snapshot",
|
|
21
|
+
"build_core_config_row",
|
|
15
22
|
"build_runtime_headers",
|
|
16
23
|
]
|
|
@@ -50,16 +50,55 @@ def build_config_snapshot(
|
|
|
50
50
|
container_id: str = "test-container",
|
|
51
51
|
integration_id: str = "test-integration",
|
|
52
52
|
generation: int = 1,
|
|
53
|
+
deleted_config_ids: list[str] | None = None,
|
|
54
|
+
config_hash: str | None = None,
|
|
55
|
+
schema_version: int = 1,
|
|
56
|
+
updated_at: str | None = None,
|
|
53
57
|
extra: dict[str, Any] | None = None,
|
|
54
58
|
) -> dict[str, Any]:
|
|
55
59
|
"""Build a snapshot payload for `/config/sync` style tests."""
|
|
56
60
|
|
|
57
61
|
payload: dict[str, Any] = {
|
|
62
|
+
"schema_version": schema_version,
|
|
58
63
|
"container_id": container_id,
|
|
59
64
|
"integration_id": integration_id,
|
|
60
65
|
"generation": generation,
|
|
61
66
|
"configs": configs or [],
|
|
67
|
+
"deleted_config_ids": deleted_config_ids or [],
|
|
62
68
|
}
|
|
69
|
+
if config_hash is not None:
|
|
70
|
+
payload["config_hash"] = config_hash
|
|
71
|
+
if updated_at is not None:
|
|
72
|
+
payload["updated_at"] = updated_at
|
|
63
73
|
if extra:
|
|
64
74
|
payload.update(extra)
|
|
65
75
|
return payload
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def build_core_config_row(
|
|
79
|
+
*,
|
|
80
|
+
config_data: dict[str, Any] | None = None,
|
|
81
|
+
config_id: str = "config-1",
|
|
82
|
+
container_id: str = "test-container",
|
|
83
|
+
integration_id: str = "test-integration",
|
|
84
|
+
generation: int = 1,
|
|
85
|
+
extra: dict[str, Any] | None = None,
|
|
86
|
+
) -> dict[str, Any]:
|
|
87
|
+
"""Build a Core database-shaped config row for startup rehydrate tests."""
|
|
88
|
+
|
|
89
|
+
payload = build_config_payload(
|
|
90
|
+
config_id=config_id,
|
|
91
|
+
container_id=container_id,
|
|
92
|
+
integration_id=integration_id,
|
|
93
|
+
extra=config_data,
|
|
94
|
+
)
|
|
95
|
+
row: dict[str, Any] = {
|
|
96
|
+
"id": config_id,
|
|
97
|
+
"container_id": container_id,
|
|
98
|
+
"integration_id": integration_id,
|
|
99
|
+
"generation": generation,
|
|
100
|
+
"config_data": payload,
|
|
101
|
+
}
|
|
102
|
+
if extra:
|
|
103
|
+
row.update(extra)
|
|
104
|
+
return row
|
|
@@ -9,6 +9,7 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
TELEMETRY_PATH = "/api/v2/integrations/telemetry"
|
|
11
11
|
EVENT_PATH = "/api/v2/events/ingest"
|
|
12
|
+
RUNTIME_CONFIG_FETCH_PATH = "/api/v2/integrations/config/fetch/all/by/container/internal"
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
@dataclass(slots=True)
|
|
@@ -24,23 +25,48 @@ class _RequestStore:
|
|
|
24
25
|
def __init__(self) -> None:
|
|
25
26
|
self.telemetry_requests: list[CapturedRequest] = []
|
|
26
27
|
self.event_requests: list[CapturedRequest] = []
|
|
28
|
+
self.runtime_config_requests: list[CapturedRequest] = []
|
|
27
29
|
self.telemetry_status = 200
|
|
28
30
|
self.event_status = 200
|
|
31
|
+
self.runtime_config_status = 200
|
|
29
32
|
self.telemetry_json: Any = {"ok": True}
|
|
30
33
|
self.event_json: Any = {"ok": True}
|
|
34
|
+
self.runtime_config_json: Any = []
|
|
31
35
|
|
|
32
36
|
def reset(self) -> None:
|
|
33
37
|
self.telemetry_requests.clear()
|
|
34
38
|
self.event_requests.clear()
|
|
39
|
+
self.runtime_config_requests.clear()
|
|
35
40
|
self.telemetry_status = 200
|
|
36
41
|
self.event_status = 200
|
|
42
|
+
self.runtime_config_status = 200
|
|
37
43
|
self.telemetry_json = {"ok": True}
|
|
38
44
|
self.event_json = {"ok": True}
|
|
45
|
+
self.runtime_config_json = []
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
class _MockCoreRequestHandler(BaseHTTPRequestHandler):
|
|
42
49
|
store: _RequestStore
|
|
43
50
|
|
|
51
|
+
def do_GET(self) -> None: # noqa: N802
|
|
52
|
+
request = CapturedRequest(
|
|
53
|
+
method="GET",
|
|
54
|
+
path=self.path,
|
|
55
|
+
headers={key: value for key, value in self.headers.items()},
|
|
56
|
+
body=b"",
|
|
57
|
+
json_body=None,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if self.path.split("?", 1)[0] == RUNTIME_CONFIG_FETCH_PATH:
|
|
61
|
+
self.store.runtime_config_requests.append(request)
|
|
62
|
+
self._send_json(
|
|
63
|
+
self.store.runtime_config_status,
|
|
64
|
+
self.store.runtime_config_json,
|
|
65
|
+
)
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
self._send_json(404, {"ok": False, "detail": "unknown path"})
|
|
69
|
+
|
|
44
70
|
def do_POST(self) -> None: # noqa: N802
|
|
45
71
|
content_length = int(self.headers.get("Content-Length", "0"))
|
|
46
72
|
body = self.rfile.read(content_length)
|
|
@@ -119,6 +145,10 @@ class MockCoreServer:
|
|
|
119
145
|
def event_requests(self) -> list[CapturedRequest]:
|
|
120
146
|
return self._store.event_requests
|
|
121
147
|
|
|
148
|
+
@property
|
|
149
|
+
def runtime_config_requests(self) -> list[CapturedRequest]:
|
|
150
|
+
return self._store.runtime_config_requests
|
|
151
|
+
|
|
122
152
|
def set_telemetry_response(self, *, status_code: int = 200, json_body: Any = None) -> None:
|
|
123
153
|
self._store.telemetry_status = status_code
|
|
124
154
|
self._store.telemetry_json = {"ok": status_code < 400} if json_body is None else json_body
|
|
@@ -127,6 +157,13 @@ class MockCoreServer:
|
|
|
127
157
|
self._store.event_status = status_code
|
|
128
158
|
self._store.event_json = {"ok": status_code < 400} if json_body is None else json_body
|
|
129
159
|
|
|
160
|
+
def set_runtime_config_response(self, *, status_code: int = 200, json_body: Any = None) -> None:
|
|
161
|
+
self._store.runtime_config_status = status_code
|
|
162
|
+
self._store.runtime_config_json = [] if json_body is None else json_body
|
|
163
|
+
|
|
164
|
+
def set_runtime_config_rows(self, rows: list[dict[str, Any]]) -> None:
|
|
165
|
+
self.set_runtime_config_response(status_code=200, json_body=rows)
|
|
166
|
+
|
|
130
167
|
def reset(self) -> None:
|
|
131
168
|
self._store.reset()
|
|
132
169
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
piphi_runtime_testkit_python-0.1.2.dist-info/METADATA,sha256=vtARpxGqDCRUiKNBaNTk6t43wKMNFOU4_E4KzSV45UA,25426
|
|
2
|
+
piphi_runtime_testkit_python-0.1.2.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90
|
|
3
|
+
piphi_runtime_testkit_python-0.1.2.dist-info/entry_points.txt,sha256=zTIXoQOJK3VVIMOfKpB5Y3vnSbyFgyU45GZCb7fLGHI,120
|
|
4
|
+
piphi_runtime_testkit_python-0.1.2.dist-info/licenses/LICENSE,sha256=pS6szQI4X7qAin1ODdoDp-XwZvsFy6ZZ28-JAwGHgzo,1070
|
|
5
|
+
piphi_runtime_testkit_python/__init__.py,sha256=Fy3rD1zp3NH_g4__52H7CWUeY0ErwTI8ChDRvlj361Y,668
|
|
6
|
+
piphi_runtime_testkit_python/assertions.py,sha256=g-lNyYwbpKYB3VduR9K8aFwKzMIFor0K2svBn_TfzxU,6882
|
|
7
|
+
piphi_runtime_testkit_python/builders.py,sha256=UmxPB1fSDGqhQzcpmmzBH4w3ZSGxtWHXQ4bfZL18kd0,2961
|
|
8
|
+
piphi_runtime_testkit_python/mock_core.py,sha256=vpAF0xDvoPHLoKbKuoxm3n1l92Yz28QxBlJNGe91oWk,6692
|
|
9
|
+
piphi_runtime_testkit_python/pytest_plugin.py,sha256=8LUxO-2o7PZOQeMLQ2THbtfwn2HJ91vXkwGiYipmNuw,965
|
|
10
|
+
piphi_runtime_testkit_python-0.1.2.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
piphi_runtime_testkit_python-0.1.1.dist-info/METADATA,sha256=RXYsA-sGse_dMF_B6B3T3bZ_T1cKlA-7U1fy7VRk0XU,25426
|
|
2
|
-
piphi_runtime_testkit_python-0.1.1.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90
|
|
3
|
-
piphi_runtime_testkit_python-0.1.1.dist-info/entry_points.txt,sha256=zTIXoQOJK3VVIMOfKpB5Y3vnSbyFgyU45GZCb7fLGHI,120
|
|
4
|
-
piphi_runtime_testkit_python-0.1.1.dist-info/licenses/LICENSE,sha256=pS6szQI4X7qAin1ODdoDp-XwZvsFy6ZZ28-JAwGHgzo,1070
|
|
5
|
-
piphi_runtime_testkit_python/__init__.py,sha256=j8QfREn-Uqx_XkWVqeEOLvyoBr9Xye5PO_0ZmbvZe-U,535
|
|
6
|
-
piphi_runtime_testkit_python/assertions.py,sha256=g-lNyYwbpKYB3VduR9K8aFwKzMIFor0K2svBn_TfzxU,6882
|
|
7
|
-
piphi_runtime_testkit_python/builders.py,sha256=fRB1W4-OwzyNhqiIbAbU9Sg2n5SKNcoKquHbN46zQdM,1760
|
|
8
|
-
piphi_runtime_testkit_python/mock_core.py,sha256=Sqwl_sJ63scYkW3CIsSpAowjynFAyeAcjWwdQ3xtgfc,5180
|
|
9
|
-
piphi_runtime_testkit_python/pytest_plugin.py,sha256=8LUxO-2o7PZOQeMLQ2THbtfwn2HJ91vXkwGiYipmNuw,965
|
|
10
|
-
piphi_runtime_testkit_python-0.1.1.dist-info/RECORD,,
|
{piphi_runtime_testkit_python-0.1.1.dist-info → piphi_runtime_testkit_python-0.1.2.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|