Skip to content

Commit a0966a0

Browse files
authored
Merge pull request #679 from simvue-io/wk9874/user_alert_test
Added extra offline mode tests
2 parents 9b209fc + b717d99 commit a0966a0

File tree

6 files changed

+123
-21
lines changed

6 files changed

+123
-21
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ repos:
2323
args: [--branch, main, --branch, dev]
2424
- id: check-added-large-files
2525
- repo: https://github.com/astral-sh/ruff-pre-commit
26-
rev: v0.9.4
26+
rev: v0.9.6
2727
hooks:
2828
- id: ruff
2929
args: [ --fix, --exit-non-zero-on-fix, "--ignore=C901" ]

simvue/api/objects/metrics.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __init__(
3737
def new(
3838
cls, *, run: str, offline: bool = False, metrics: list[MetricSet], **kwargs
3939
):
40-
"""Create a new Events entry on the Simvue server"""
40+
"""Create a new Metrics entry on the Simvue server"""
4141
return Metrics(
4242
run=run,
4343
metrics=[metric.model_dump() for metric in metrics],
@@ -51,27 +51,23 @@ def get(
5151
cls,
5252
metrics: list[str],
5353
xaxis: typing.Literal["timestamp", "step", "time"],
54+
runs: list[str],
5455
*,
5556
count: pydantic.PositiveInt | None = None,
5657
offset: pydantic.PositiveInt | None = None,
5758
**kwargs,
5859
) -> typing.Generator[MetricSet, None, None]:
5960
_class_instance = cls(_read_only=True, _local=True)
60-
if (
61-
_data := cls._get_all_objects(
62-
count,
63-
offset,
64-
metrics=json.dumps(metrics),
65-
xaxis=xaxis,
66-
**kwargs,
67-
).get("data")
68-
) is None:
69-
raise RuntimeError(
70-
f"Expected key 'data' for retrieval of {_class_instance.__class__.__name__.lower()}s"
71-
)
72-
73-
for _entry in _data:
74-
yield MetricSet(**_entry)
61+
_data = cls._get_all_objects(
62+
count,
63+
offset,
64+
metrics=json.dumps(metrics),
65+
runs=json.dumps(runs),
66+
xaxis=xaxis,
67+
**kwargs,
68+
)
69+
# TODO: Temp fix, just return the dictionary. Not sure what format we really want this in...
70+
return _data
7571

7672
@pydantic.validate_call
7773
def span(self, run_ids: list[str]) -> dict[str, int | float]:

tests/functional/test_dispatch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ def callback(___: list[typing.Any], _: str, args=check_dict, var=variable) -> No
6767
event.set()
6868

6969
dispatcher.join()
70+
time.sleep(0.1)
7071

7172
for variable in variables:
72-
assert check_dict[variable]["counter"] >= 2 if overload_buffer else 1, f"Check of counter for dispatcher '{variable}' failed with count = {check_dict[variable]['counter']}"
73+
assert check_dict[variable]["counter"] >= (2 if overload_buffer else 1), f"Check of counter for dispatcher '{variable}' failed with count = {check_dict[variable]['counter']}"
7374
assert time.time() - start_time < time_threshold
7475

7576

tests/unit/test_events.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from simvue.api.objects import Events, Folder, Run
99
from simvue.models import DATETIME_FORMAT
10+
from simvue.sender import sender
1011

1112
@pytest.mark.api
1213
@pytest.mark.online
@@ -30,3 +31,39 @@ def test_events_creation_online() -> None:
3031
_run.delete()
3132
_folder.delete(recursive=True, delete_runs=True, runs_only=False)
3233

34+
@pytest.mark.api
35+
@pytest.mark.offline
36+
def test_events_creation_offline() -> None:
37+
_uuid: str = f"{uuid.uuid4()}".split("-")[0]
38+
_folder_name = f"/simvue_unit_testing/{_uuid}"
39+
_folder = Folder.new(path=_folder_name, offline=True)
40+
_run = Run.new(folder=_folder_name, offline=True)
41+
_folder.commit()
42+
_run.commit()
43+
_timestamp = datetime.datetime.now().strftime(DATETIME_FORMAT)
44+
_events = Events.new(
45+
run=_run.id,
46+
events=[
47+
{"message": "This is a test!", "timestamp": _timestamp}
48+
],
49+
offline=True
50+
)
51+
_events.commit()
52+
with _events._local_staging_file.open() as in_f:
53+
_local_data = json.load(in_f)
54+
55+
assert _local_data.get("run") == _run.id
56+
assert _local_data.get("events")[0].get("message") == "This is a test!"
57+
assert _local_data.get("events")[0].get("timestamp") == _timestamp
58+
59+
_id_mapping = sender(_events._local_staging_file.parents[1], 1, 10, ["folders", "runs", "events"])
60+
time.sleep(1)
61+
62+
# Get online version of events
63+
_online_events = Events(_id_mapping.get(_events.id))
64+
_event_content = next(_online_events.get(run_id=_id_mapping.get(_run.id)))
65+
assert _event_content.message == "This is a test!"
66+
assert _event_content.timestamp == _timestamp
67+
68+
_run.delete()
69+
_folder.delete(recursive=True, delete_runs=True, runs_only=False)

tests/unit/test_metrics.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import uuid
77

88
from simvue.api.objects import Metrics, Folder, Run
9+
from simvue.models import DATETIME_FORMAT
10+
from simvue.sender import sender
911

1012
@pytest.mark.api
1113
@pytest.mark.online
@@ -38,9 +40,60 @@ def test_metrics_creation_online() -> None:
3840
)
3941
assert _metrics.to_dict()
4042
_metrics.commit()
41-
assert _metrics.get(metrics=["x", "y", "z"], xaxis="step")
43+
assert _metrics.get(metrics=["x", "y", "z"], xaxis="step", runs=[_run.id])
4244
assert _metrics.span(run_ids=[_run.id])
4345
assert _metrics.names(run_ids=[_run.id])
4446
_run.delete()
4547
_folder.delete(recursive=True, delete_runs=True, runs_only=False)
4648

49+
@pytest.mark.api
50+
@pytest.mark.offline
51+
def test_metrics_creation_offline() -> None:
52+
_uuid: str = f"{uuid.uuid4()}".split("-")[0]
53+
_folder_name = f"/simvue_unit_testing/{_uuid}"
54+
_folder = Folder.new(path=_folder_name, offline=True)
55+
_run = Run.new(name="hello", folder=_folder_name, offline=True)
56+
_folder.commit()
57+
_run.commit()
58+
59+
_values = {
60+
"x": 1,
61+
"y": 2.0,
62+
"z": True
63+
}
64+
_time: int = 1
65+
_step: int = 1
66+
_timestamp = datetime.datetime.now().strftime(DATETIME_FORMAT)
67+
_metrics = Metrics.new(
68+
run=_run.id,
69+
metrics=[
70+
{
71+
"timestamp": _timestamp,
72+
"time": _time,
73+
"step": _step,
74+
"values": _values,
75+
}
76+
],
77+
offline=True
78+
)
79+
_metrics.commit()
80+
with _metrics._local_staging_file.open() as in_f:
81+
_local_data = json.load(in_f)
82+
83+
assert _local_data.get("run") == _run.id
84+
assert _local_data.get("metrics")[0].get("values") == _values
85+
assert _local_data.get("metrics")[0].get("timestamp") == _timestamp
86+
assert _local_data.get("metrics")[0].get("step") == _step
87+
assert _local_data.get("metrics")[0].get("time") == _time
88+
89+
_id_mapping = sender(_metrics._local_staging_file.parents[1], 1, 10, ["folders", "runs", "metrics"])
90+
time.sleep(1)
91+
92+
# Get online version of metrics
93+
_online_metrics = Metrics(_id_mapping.get(_metrics.id))
94+
_data = _online_metrics.get(metrics=["x", "y", "z"], runs=[_id_mapping.get(_run.id)], xaxis="step")
95+
assert sorted(_online_metrics.names(run_ids=[_id_mapping.get(_run.id)])) == sorted(_values.keys())
96+
assert _data.get(_id_mapping.get(_run.id)).get('y')[0].get('value') == 2.0
97+
assert _data.get(_id_mapping.get(_run.id)).get('y')[0].get('step') == 1
98+
_run.delete()
99+
_folder.delete(recursive=True, delete_runs=True, runs_only=False)

tests/unit/test_user_alert.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,28 @@ def test_user_alert_status_offline() -> None:
191191
_run.alerts = [_alert.id]
192192
_run.commit()
193193

194-
sender(_alert._local_staging_file.parents[1], 1, 10, ["folders", "runs", "alerts"])
194+
_id_mapping = sender(_alert._local_staging_file.parents[1], 1, 10, ["folders", "runs", "alerts"])
195195
time.sleep(1)
196+
197+
# Get online aler, check status is not set
198+
_online_alert = UserAlert(_id_mapping.get(_alert.id))
199+
assert not _online_alert.get_status(run_id=_id_mapping.get(_run.id))
196200

197201
_alert.set_status(_run.id, "critical")
198202
_alert.commit()
199-
import pdb; pdb.set_trace()
200203
time.sleep(1)
204+
205+
# Check online status is still not set as change has not been sent
206+
_online_alert.refresh()
207+
assert not _online_alert.get_status(run_id=_id_mapping.get(_run.id))
208+
209+
sender(_alert._local_staging_file.parents[1], 1, 10, ["alerts"])
210+
time.sleep(1)
211+
212+
# Check online status has been updated
213+
_online_alert.refresh()
214+
assert _online_alert.get_status(run_id=_id_mapping.get(_run.id)) == "critical"
215+
201216
_run.delete()
202217
_folder.delete(recursive=True, runs_only=False, delete_runs=True)
203218
_alert.delete()

0 commit comments

Comments
 (0)