Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions aw_server/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from aw_core.log import get_log_file_path
from aw_core.models import Event
from aw_query import query2
from aw_query.exceptions import QueryException
from aw_transform import heartbeat_merge

from .__about__ import __version__
Expand Down Expand Up @@ -342,8 +343,16 @@ def query2(self, name, query, timeperiods, cache):
period = timeperiod.split("/")[
:2
] # iso8601 timeperiods are separated by a slash
starttime = iso8601.parse_date(period[0])
endtime = iso8601.parse_date(period[1])
if len(period) != 2:
raise QueryException(
f"Invalid timeperiod '{timeperiod}': expected two ISO8601 "
"datetimes separated by a slash (start/end)"
)
try:
starttime = iso8601.parse_date(period[0])
endtime = iso8601.parse_date(period[1])
except iso8601.ParseError as e:
raise QueryException(f"Invalid timeperiod '{timeperiod}': {e}")
query = "".join(query)
result.append(query2.query(name, query, starttime, endtime, self.db))
return result
Expand Down
40 changes: 40 additions & 0 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,43 @@ def get_events():


# TODO: Add benchmark for basic AFK-filtering query


def test_query_invalid_timeperiod(flask_client):
"""Malformed timeperiods must yield 400 (client error), not 500.

Regression test: a non-ISO8601 timeperiod previously raised an uncaught
iso8601.ParseError, surfacing as an Internal Server Error.
"""
r = flask_client.post(
"/api/0/query/",
json={"query": ["RETURN = 1;"], "timeperiods": ["not-a-valid-period"]},
)
assert r.status_code == 400
assert "not-a-valid-period" in r.json["message"]
Comment on lines +94 to +105
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 iso8601.ParseError handler is untested

"not-a-valid-period" contains no slash, so it is caught by the new len(period) != 2 guard before the try/except iso8601.ParseError block is ever reached. The actual except iso8601.ParseError branch — triggered by inputs like "not-valid/also-not-valid" (two slash-separated parts, neither parseable as ISO 8601) — has no test covering it. If that handler were accidentally removed or malformed, the existing suite would still pass.



def test_query_timeperiod_missing_slash(flask_client):
"""A timeperiod without a start/end slash separator must yield 400, not 500.

Regression test: a single ISO8601 datetime (no slash) previously raised an
uncaught IndexError when indexing the split result.
"""
r = flask_client.post(
"/api/0/query/",
json={"query": ["RETURN = 1;"], "timeperiods": ["2024-01-01T00:00:00+00:00"]},
)
assert r.status_code == 400


def test_query_valid_timeperiod(flask_client):
"""A well-formed query with a valid timeperiod still succeeds."""
r = flask_client.post(
"/api/0/query/",
json={
"query": ["RETURN = 1;"],
"timeperiods": ["2024-01-01T00:00:00+00:00/2024-01-02T00:00:00+00:00"],
},
)
assert r.status_code == 200
assert r.json == [1]
Loading