Skip to content

Commit 8a1e92f

Browse files
authored
FakeService: filter: Fix field-existance check (#212)
2 parents d7d2e37 + 721b3db commit 8a1e92f

File tree

3 files changed

+160
-8
lines changed

3 files changed

+160
-8
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414

1515
## Bug Fixes
1616

17-
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
17+
* The `FakeService` filter list code is now properly checking for unset fields to filter for.

src/frequenz/client/dispatch/test/_service.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,20 +149,23 @@ def _filter_dispatch(
149149
if target != dispatch.target:
150150
return False
151151
if _filter.HasField("start_time_interval"):
152-
if start_from := _filter.start_time_interval.start_time:
152+
if _filter.start_time_interval.HasField("start_time"):
153+
start_from = _filter.start_time_interval.start_time
153154
if dispatch.start_time < _to_dt(start_from):
154155
return False
155-
if start_to := _filter.start_time_interval.end_time:
156+
if _filter.start_time_interval.HasField("end_time"):
157+
start_to = _filter.start_time_interval.end_time
156158
if dispatch.start_time >= _to_dt(start_to):
157159
return False
158160
if _filter.HasField("end_time_interval"):
159-
if end_from := _filter.end_time_interval.start_time:
160-
if (
161-
dispatch.duration
162-
and dispatch.start_time + dispatch.duration < _to_dt(end_from)
161+
if _filter.end_time_interval.HasField("start_time"):
162+
end_from = _filter.end_time_interval.start_time
163+
if dispatch.duration and (
164+
dispatch.start_time + dispatch.duration < _to_dt(end_from)
163165
):
164166
return False
165-
if end_to := _filter.end_time_interval.end_time:
167+
if _filter.end_time_interval.HasField("end_time"):
168+
end_to = _filter.end_time_interval.end_time
166169
if (
167170
dispatch.duration
168171
and dispatch.start_time + dispatch.duration >= _to_dt(end_to)

tests/test_service.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Tests for the frequenz.client.dispatch.test._service package."""
5+
6+
from datetime import datetime, timedelta, timezone
7+
8+
from frequenz.api.common.v1alpha8.pagination.pagination_params_pb2 import (
9+
PaginationParams,
10+
)
11+
12+
# pylint: disable=no-name-in-module
13+
from frequenz.api.common.v1alpha8.types.interval_pb2 import Interval as PBInterval
14+
from frequenz.api.dispatch.v1.dispatch_pb2 import (
15+
DispatchFilter,
16+
ListMicrogridDispatchesRequest,
17+
)
18+
19+
from frequenz.client.base.conversion import to_timestamp
20+
from frequenz.client.common.microgrid import MicrogridId
21+
from frequenz.client.dispatch.recurrence import RecurrenceRule
22+
from frequenz.client.dispatch.test._service import FakeService
23+
from frequenz.client.dispatch.types import (
24+
Dispatch,
25+
DispatchId,
26+
TargetIds,
27+
)
28+
29+
30+
async def test_list_dispatches_filter_start_time() -> None:
31+
"""Test listing dispatches with a start time filter."""
32+
service = FakeService()
33+
now = datetime.now(timezone.utc)
34+
dispatches = [
35+
Dispatch(
36+
id=DispatchId(i),
37+
start_time=now + timedelta(minutes=i),
38+
duration=timedelta(minutes=1),
39+
type="test",
40+
target=TargetIds(1),
41+
active=True,
42+
dry_run=False,
43+
payload={},
44+
recurrence=RecurrenceRule(),
45+
create_time=now,
46+
update_time=now,
47+
)
48+
for i in range(10)
49+
]
50+
service.dispatches[MicrogridId(1)] = dispatches
51+
52+
# Filter for dispatches starting after now + 5 minutes
53+
req = ListMicrogridDispatchesRequest(
54+
microgrid_id=1,
55+
filter=DispatchFilter(
56+
start_time_interval=PBInterval(
57+
start_time=to_timestamp(now + timedelta(minutes=5)),
58+
end_time=None,
59+
)
60+
),
61+
)
62+
filtered_dispatches = [
63+
Dispatch.from_protobuf(dispatch)
64+
for dispatch in (await service.ListMicrogridDispatches(req)).dispatches
65+
]
66+
assert len(filtered_dispatches) == 5
67+
assert all(d.start_time >= now + timedelta(minutes=5) for d in filtered_dispatches)
68+
69+
# Filter for dispatches starting before now + 5 minutes
70+
req = ListMicrogridDispatchesRequest(
71+
microgrid_id=1,
72+
filter=DispatchFilter(
73+
start_time_interval=PBInterval(
74+
start_time=None,
75+
end_time=to_timestamp(now + timedelta(minutes=5)),
76+
)
77+
),
78+
pagination_params=PaginationParams(page_size=100),
79+
)
80+
filtered_dispatches = [
81+
Dispatch.from_protobuf(dispatch)
82+
for dispatch in (await service.ListMicrogridDispatches(req)).dispatches
83+
]
84+
assert len(filtered_dispatches) == 5
85+
assert all(d.start_time < now + timedelta(minutes=5) for d in filtered_dispatches)
86+
87+
88+
async def test_list_dispatches_filter_end_time() -> None:
89+
"""Test listing dispatches with an end time filter."""
90+
service = FakeService()
91+
now = datetime.now(timezone.utc)
92+
dispatches = [
93+
Dispatch(
94+
id=DispatchId(i),
95+
start_time=now,
96+
duration=timedelta(minutes=i),
97+
type="test",
98+
target=TargetIds(1),
99+
active=True,
100+
dry_run=False,
101+
payload={},
102+
recurrence=RecurrenceRule(),
103+
create_time=now,
104+
update_time=now,
105+
)
106+
for i in range(1, 11)
107+
]
108+
service.dispatches[MicrogridId(1)] = dispatches
109+
110+
# Filter for dispatches ending after now + 5 minutes
111+
req = ListMicrogridDispatchesRequest(
112+
microgrid_id=1,
113+
filter=DispatchFilter(
114+
end_time_interval=PBInterval(
115+
start_time=to_timestamp(now + timedelta(minutes=5)),
116+
end_time=None,
117+
)
118+
),
119+
pagination_params=PaginationParams(page_size=100),
120+
)
121+
filtered_dispatches = [
122+
Dispatch.from_protobuf(dispatch)
123+
for dispatch in (await service.ListMicrogridDispatches(req)).dispatches
124+
]
125+
assert len(filtered_dispatches) == 6
126+
assert all(
127+
d.start_time + d.duration >= now + timedelta(minutes=5) # type: ignore[operator]
128+
for d in filtered_dispatches
129+
)
130+
131+
# Filter for dispatches ending before now + 5 minutes
132+
req = ListMicrogridDispatchesRequest(
133+
microgrid_id=1,
134+
filter=DispatchFilter(
135+
end_time_interval=PBInterval(
136+
start_time=None,
137+
end_time=to_timestamp(now + timedelta(minutes=5)),
138+
)
139+
),
140+
)
141+
filtered_dispatches = [
142+
Dispatch.from_protobuf(dispatch)
143+
for dispatch in (await service.ListMicrogridDispatches(req)).dispatches
144+
]
145+
assert len(filtered_dispatches) == 4
146+
assert all(
147+
d.start_time + d.duration < now + timedelta(minutes=5) # type: ignore[operator]
148+
for d in filtered_dispatches
149+
)

0 commit comments

Comments
 (0)