87 lines
2.8 KiB
Python
87 lines
2.8 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import asyncio
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from cmvr_edge_ai.core import (
|
||
|
|
EdgeQueue,
|
||
|
|
EdgeQueueClosed,
|
||
|
|
EdgeQueueFull,
|
||
|
|
OverflowPolicy,
|
||
|
|
PutResult,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_drop_oldest_keeps_the_freshest_items_and_updates_stats() -> None:
|
||
|
|
async def exercise(): # type: ignore[no-untyped-def]
|
||
|
|
queue = EdgeQueue[int](2, OverflowPolicy.DROP_OLDEST, name="camera")
|
||
|
|
assert await queue.put(1) is PutResult.ENQUEUED
|
||
|
|
assert await queue.put(2) is PutResult.ENQUEUED
|
||
|
|
assert await queue.put(3) is PutResult.DROPPED_OLDEST
|
||
|
|
assert [await queue.get(), await queue.get()] == [2, 3]
|
||
|
|
await queue.close()
|
||
|
|
with pytest.raises(EdgeQueueClosed, match="camera"):
|
||
|
|
await queue.get()
|
||
|
|
return queue.stats()
|
||
|
|
|
||
|
|
stats = asyncio.run(exercise())
|
||
|
|
|
||
|
|
assert stats.enqueued == 3
|
||
|
|
assert stats.dequeued == 2
|
||
|
|
assert stats.dropped_oldest == 1
|
||
|
|
assert stats.high_watermark == 2
|
||
|
|
assert stats.closed is True
|
||
|
|
|
||
|
|
|
||
|
|
def test_drop_newest_preserves_queued_items() -> None:
|
||
|
|
async def exercise(): # type: ignore[no-untyped-def]
|
||
|
|
queue = EdgeQueue[str](2, "drop_newest")
|
||
|
|
await queue.put("first")
|
||
|
|
await queue.put("second")
|
||
|
|
result = await queue.put("third")
|
||
|
|
items = [await queue.get(), await queue.get()]
|
||
|
|
return result, items, queue.stats()
|
||
|
|
|
||
|
|
result, items, stats = asyncio.run(exercise())
|
||
|
|
|
||
|
|
assert result is PutResult.DROPPED_NEWEST
|
||
|
|
assert items == ["first", "second"]
|
||
|
|
assert stats.enqueued == 2
|
||
|
|
assert stats.dropped_newest == 1
|
||
|
|
|
||
|
|
|
||
|
|
def test_reject_policy_raises_without_mutating_contents() -> None:
|
||
|
|
async def exercise(): # type: ignore[no-untyped-def]
|
||
|
|
queue = EdgeQueue[str](1, "reject", name="control")
|
||
|
|
await queue.put("accepted")
|
||
|
|
with pytest.raises(EdgeQueueFull, match="control"):
|
||
|
|
await queue.put("rejected")
|
||
|
|
return await queue.get(), queue.stats()
|
||
|
|
|
||
|
|
item, stats = asyncio.run(exercise())
|
||
|
|
|
||
|
|
assert item == "accepted"
|
||
|
|
assert stats.enqueued == 1
|
||
|
|
assert stats.rejected == 1
|
||
|
|
|
||
|
|
|
||
|
|
def test_block_policy_releases_producer_after_consumer_makes_space() -> None:
|
||
|
|
async def exercise(): # type: ignore[no-untyped-def]
|
||
|
|
queue = EdgeQueue[str](1, "block")
|
||
|
|
await queue.put("first")
|
||
|
|
pending_put = asyncio.create_task(queue.put("second"))
|
||
|
|
await asyncio.sleep(0)
|
||
|
|
assert pending_put.done() is False
|
||
|
|
|
||
|
|
first = await queue.get()
|
||
|
|
put_result = await asyncio.wait_for(pending_put, timeout=1)
|
||
|
|
second = await queue.get()
|
||
|
|
return first, second, put_result, queue.stats()
|
||
|
|
|
||
|
|
first, second, put_result, stats = asyncio.run(exercise())
|
||
|
|
|
||
|
|
assert (first, second) == ("first", "second")
|
||
|
|
assert put_result is PutResult.ENQUEUED
|
||
|
|
assert stats.blocked_puts == 1
|