Skip to content

Commit e3cd812

Browse files
committed
chore(python-sdk): Update tests
1 parent c10f785 commit e3cd812

File tree

2 files changed

+107
-24
lines changed

2 files changed

+107
-24
lines changed

tests/aignostics/application/utils_test.py

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,62 +229,133 @@ def test_application_run_status_to_str_terminated() -> None:
229229
# Tests for is_not_terminated_with_deadline_exceeded
230230

231231

232+
# --- Tests using scheduling response object (new primary path) ---
233+
234+
235+
@pytest.mark.unit
236+
def test_is_not_terminated_with_deadline_exceeded_scheduling_object_terminated_run() -> None:
237+
"""Test that terminated runs always return None regardless of scheduling deadline."""
238+
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
239+
scheduling = Mock(deadline=past_deadline)
240+
result = is_not_terminated_with_deadline_exceeded(RunState.TERMINATED, scheduling=scheduling)
241+
assert result is None
242+
243+
244+
@pytest.mark.unit
245+
def test_is_not_terminated_with_deadline_exceeded_scheduling_object_pending_future() -> None:
246+
"""Test that a pending run with scheduling deadline in the future returns False."""
247+
from datetime import timedelta
248+
249+
future_deadline = datetime.now(tz=UTC) + timedelta(hours=1)
250+
scheduling = Mock(deadline=future_deadline)
251+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, scheduling=scheduling)
252+
assert result is False
253+
254+
255+
@pytest.mark.unit
256+
def test_is_not_terminated_with_deadline_exceeded_scheduling_object_pending_past() -> None:
257+
"""Test that a pending run with scheduling deadline in the past returns True."""
258+
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
259+
scheduling = Mock(deadline=past_deadline)
260+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, scheduling=scheduling)
261+
assert result is True
262+
263+
264+
@pytest.mark.unit
265+
def test_is_not_terminated_with_deadline_exceeded_scheduling_object_processing_past() -> None:
266+
"""Test that a processing run with scheduling deadline in the past returns True."""
267+
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
268+
scheduling = Mock(deadline=past_deadline)
269+
result = is_not_terminated_with_deadline_exceeded(RunState.PROCESSING, scheduling=scheduling)
270+
assert result is True
271+
272+
273+
@pytest.mark.unit
274+
def test_is_not_terminated_with_deadline_exceeded_scheduling_object_none_deadline() -> None:
275+
"""Test that scheduling object with None deadline returns None."""
276+
scheduling = Mock(deadline=None)
277+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, scheduling=scheduling)
278+
assert result is None
279+
280+
281+
@pytest.mark.unit
282+
def test_is_not_terminated_with_deadline_exceeded_scheduling_none() -> None:
283+
"""Test that None scheduling and None metadata returns None."""
284+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, scheduling=None, custom_metadata=None)
285+
assert result is None
286+
287+
288+
@pytest.mark.unit
289+
def test_is_not_terminated_with_deadline_exceeded_scheduling_takes_precedence() -> None:
290+
"""Test that scheduling object takes precedence over custom_metadata."""
291+
from datetime import timedelta
292+
293+
# scheduling says future (not exceeded), custom_metadata says past (exceeded)
294+
future_deadline = datetime.now(tz=UTC) + timedelta(hours=1)
295+
scheduling = Mock(deadline=future_deadline)
296+
metadata = {"sdk": {"scheduling": {"deadline": "2020-01-01T12:00:00Z"}}}
297+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, scheduling=scheduling, custom_metadata=metadata)
298+
assert result is False # scheduling wins
299+
300+
301+
# --- Tests using custom_metadata fallback (backward compatibility for older runs) ---
302+
303+
232304
@pytest.mark.unit
233305
def test_is_not_terminated_with_deadline_exceeded_terminated_run() -> None:
234306
"""Test that terminated runs always return None regardless of deadline."""
235307
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
236308
metadata = {"sdk": {"scheduling": {"deadline": past_deadline.isoformat()}}}
237-
result = is_not_terminated_with_deadline_exceeded(RunState.TERMINATED, metadata)
309+
result = is_not_terminated_with_deadline_exceeded(RunState.TERMINATED, custom_metadata=metadata)
238310
assert result is None
239311

240312

241313
@pytest.mark.unit
242314
def test_is_not_terminated_with_deadline_exceeded_none_metadata() -> None:
243315
"""Test that None metadata returns None."""
244-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, None)
316+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=None)
245317
assert result is None
246318

247319

248320
@pytest.mark.unit
249321
def test_is_not_terminated_with_deadline_exceeded_empty_metadata() -> None:
250322
"""Test that empty metadata returns None."""
251-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, {})
323+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata={})
252324
assert result is None
253325

254326

255327
@pytest.mark.unit
256328
def test_is_not_terminated_with_deadline_exceeded_no_sdk_key() -> None:
257329
"""Test that metadata without 'sdk' key returns None."""
258330
metadata = {"other_key": "other_value"}
259-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
331+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
260332
assert result is None
261333

262334

263335
@pytest.mark.unit
264336
def test_is_not_terminated_with_deadline_exceeded_no_scheduling_key() -> None:
265337
"""Test that metadata without 'scheduling' key returns None."""
266338
metadata = {"sdk": {"other_key": "other_value"}}
267-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
339+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
268340
assert result is None
269341

270342

271343
@pytest.mark.unit
272344
def test_is_not_terminated_with_deadline_exceeded_no_deadline_key() -> None:
273345
"""Test that metadata without 'deadline' key returns None."""
274346
metadata = {"sdk": {"scheduling": {"other_key": "other_value"}}}
275-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
347+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
276348
assert result is None
277349

278350

279351
@pytest.mark.unit
280352
def test_is_not_terminated_with_deadline_exceeded_pending_deadline_in_future() -> None:
281353
"""Test that a pending run with deadline in the future returns False."""
282-
# Create a deadline 1 hour in the future
283354
from datetime import timedelta
284355

285356
future_deadline = datetime.now(tz=UTC) + timedelta(hours=1)
286357
metadata = {"sdk": {"scheduling": {"deadline": future_deadline.isoformat()}}}
287-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
358+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
288359
assert result is False
289360

290361

@@ -293,7 +364,7 @@ def test_is_not_terminated_with_deadline_exceeded_pending_deadline_in_past() ->
293364
"""Test that a pending run with deadline in the past returns True."""
294365
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
295366
metadata = {"sdk": {"scheduling": {"deadline": past_deadline.isoformat()}}}
296-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
367+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
297368
assert result is True
298369

299370

@@ -302,15 +373,15 @@ def test_is_not_terminated_with_deadline_exceeded_processing_deadline_in_past()
302373
"""Test that a processing run with deadline in the past returns True."""
303374
past_deadline = datetime(2020, 1, 1, 12, 0, 0, tzinfo=UTC)
304375
metadata = {"sdk": {"scheduling": {"deadline": past_deadline.isoformat()}}}
305-
result = is_not_terminated_with_deadline_exceeded(RunState.PROCESSING, metadata)
376+
result = is_not_terminated_with_deadline_exceeded(RunState.PROCESSING, custom_metadata=metadata)
306377
assert result is True
307378

308379

309380
@pytest.mark.unit
310381
def test_is_not_terminated_with_deadline_exceeded_invalid_datetime_format() -> None:
311382
"""Test that invalid datetime format returns None."""
312383
metadata = {"sdk": {"scheduling": {"deadline": "not-a-valid-datetime"}}}
313-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
384+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
314385
assert result is None
315386

316387

@@ -319,7 +390,7 @@ def test_is_not_terminated_with_deadline_exceeded_deadline_with_z_suffix() -> No
319390
"""Test that deadline with Z suffix (UTC) is handled correctly for pending run."""
320391
past_deadline = "2020-01-01T12:00:00Z"
321392
metadata = {"sdk": {"scheduling": {"deadline": past_deadline}}}
322-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
393+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
323394
assert result is True
324395

325396

@@ -328,31 +399,31 @@ def test_is_not_terminated_with_deadline_exceeded_deadline_with_timezone_offset(
328399
"""Test that deadline with timezone offset is handled correctly for pending run."""
329400
past_deadline = "2020-01-01T12:00:00+00:00"
330401
metadata = {"sdk": {"scheduling": {"deadline": past_deadline}}}
331-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
402+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
332403
assert result is True
333404

334405

335406
@pytest.mark.unit
336407
def test_is_not_terminated_with_deadline_exceeded_deadline_empty_string() -> None:
337408
"""Test that empty string deadline returns None."""
338409
metadata = {"sdk": {"scheduling": {"deadline": ""}}}
339-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
410+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
340411
assert result is None
341412

342413

343414
@pytest.mark.unit
344415
def test_is_not_terminated_with_deadline_exceeded_deadline_none_value() -> None:
345416
"""Test that None deadline value returns None."""
346417
metadata = {"sdk": {"scheduling": {"deadline": None}}}
347-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
418+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
348419
assert result is None
349420

350421

351422
@pytest.mark.unit
352423
def test_is_not_terminated_with_deadline_exceeded_deadline_numeric_value() -> None:
353424
"""Test that numeric deadline value returns None."""
354425
metadata = {"sdk": {"scheduling": {"deadline": 123456789}}}
355-
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, metadata)
426+
result = is_not_terminated_with_deadline_exceeded(RunState.PENDING, custom_metadata=metadata)
356427
assert result is None
357428

358429

tests/aignostics/platform/e2e_test.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,13 @@ def _submit_and_validate( # noqa: PLR0913, PLR0917
280280

281281
logger.trace(f"Submitting application run for {application_id} version {application_version}")
282282
client = platform.Client()
283+
scheduling = {
284+
"due_date": (datetime.now(tz=UTC) + timedelta(seconds=due_date_seconds)).isoformat(),
285+
"deadline": deadline.isoformat(),
286+
}
283287
custom_metadata = {
284288
"sdk": {
285289
"tags": tags or set(),
286-
"scheduling": {
287-
"due_date": (datetime.now(tz=UTC) + timedelta(seconds=due_date_seconds)).isoformat(),
288-
"deadline": deadline.isoformat(),
289-
},
290290
"pipeline": {
291291
"gpu": {
292292
"gpu_type": PIPELINE_GPU_TYPE,
@@ -310,6 +310,7 @@ def _submit_and_validate( # noqa: PLR0913, PLR0917
310310
application_version=application_version,
311311
items=payload,
312312
custom_metadata=custom_metadata,
313+
scheduling=scheduling,
313314
)
314315

315316
# Let's validate we can fiond the run by id
@@ -430,9 +431,20 @@ def _find_and_validate(
430431
sdk_metadata = RunSdkMetadata.model_validate(details.custom_metadata.get("sdk", {}))
431432
logger.trace(sdk_metadata.model_dump_json(indent=2))
432433
print(sdk_metadata.model_dump_json(indent=2))
433-
allowed_duration = datetime.fromisoformat(sdk_metadata.scheduling.deadline) - datetime.fromisoformat(
434-
sdk_metadata.submission.date
435-
)
434+
# Read deadline from the API response scheduling field (preferred),
435+
# falling back to custom_metadata for runs submitted before this change
436+
scheduling = getattr(details, "scheduling", None)
437+
if scheduling is not None and getattr(scheduling, "deadline", None) is not None:
438+
deadline_dt = (
439+
scheduling.deadline
440+
if isinstance(scheduling.deadline, datetime)
441+
else datetime.fromisoformat(str(scheduling.deadline))
442+
)
443+
deadline_iso = deadline_dt.isoformat()
444+
else:
445+
deadline_iso = sdk_metadata.scheduling.deadline
446+
deadline_dt = datetime.fromisoformat(deadline_iso)
447+
allowed_duration = deadline_dt - datetime.fromisoformat(sdk_metadata.submission.date)
436448
allowed_hours = round(allowed_duration.total_seconds() / (60 * 60))
437449
deadline_met = details.state is RunState.TERMINATED
438450
metrics_run_attributes = {
@@ -441,7 +453,7 @@ def _find_and_validate(
441453
"application_version": application_version,
442454
"allowed_hours": allowed_hours,
443455
"submitted_at": sdk_metadata.submission.date,
444-
"deadline": sdk_metadata.scheduling.deadline,
456+
"deadline": deadline_iso,
445457
"state": details.state.value,
446458
"error_message": details.error_message,
447459
"error_code": details.error_code,

0 commit comments

Comments
 (0)