chunker and ui
This commit is contained in:
103
tests/chunker/test_collector.py
Normal file
103
tests/chunker/test_collector.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
Tests for ResultCollector — ordered reassembly, out-of-order buffering, duplicates.
|
||||
|
||||
Demonstrates: TDD (Interview Topic 8) — testing algorithms (heapq reassembly).
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from core.chunker.collector import ResultCollector
|
||||
from core.chunker.exceptions import ReassemblyError
|
||||
|
||||
|
||||
class TestResultCollector:
|
||||
def test_in_order_emission(self, make_result):
|
||||
"""Results arriving in order are emitted immediately."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
|
||||
emitted = collector.add(make_result(0))
|
||||
assert len(emitted) == 1
|
||||
assert emitted[0].sequence == 0
|
||||
|
||||
emitted = collector.add(make_result(1))
|
||||
assert len(emitted) == 1
|
||||
|
||||
emitted = collector.add(make_result(2))
|
||||
assert len(emitted) == 1
|
||||
|
||||
assert collector.is_complete
|
||||
|
||||
def test_out_of_order_buffering(self, make_result):
|
||||
"""Out-of-order results are buffered until gaps fill."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
|
||||
# Arrive: 2, 0, 1
|
||||
emitted = collector.add(make_result(2))
|
||||
assert len(emitted) == 0
|
||||
assert collector.buffered_count == 1
|
||||
|
||||
emitted = collector.add(make_result(0))
|
||||
assert len(emitted) == 1 # Only 0 emitted, 1 still missing
|
||||
|
||||
emitted = collector.add(make_result(1))
|
||||
assert len(emitted) == 2 # 1 and 2 now emittable
|
||||
assert collector.is_complete
|
||||
|
||||
def test_reverse_order(self, make_result):
|
||||
"""All results arrive in reverse — only last add emits everything."""
|
||||
collector = ResultCollector(total_chunks=4)
|
||||
|
||||
for seq in [3, 2, 1]:
|
||||
emitted = collector.add(make_result(seq))
|
||||
assert len(emitted) == 0
|
||||
|
||||
emitted = collector.add(make_result(0))
|
||||
assert len(emitted) == 4
|
||||
assert collector.is_complete
|
||||
|
||||
def test_duplicate_raises(self, make_result):
|
||||
"""Duplicate sequence number raises ReassemblyError."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
collector.add(make_result(0))
|
||||
|
||||
with pytest.raises(ReassemblyError, match="Duplicate"):
|
||||
collector.add(make_result(0))
|
||||
|
||||
def test_emitted_count(self, make_result):
|
||||
"""emitted_count tracks correctly."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
assert collector.emitted_count == 0
|
||||
|
||||
collector.add(make_result(0))
|
||||
assert collector.emitted_count == 1
|
||||
|
||||
collector.add(make_result(2)) # buffered
|
||||
assert collector.emitted_count == 1
|
||||
|
||||
collector.add(make_result(1)) # releases 1 and 2
|
||||
assert collector.emitted_count == 3
|
||||
|
||||
def test_get_ordered_results(self, make_result):
|
||||
"""get_ordered_results returns all emitted results in order."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
collector.add(make_result(2))
|
||||
collector.add(make_result(0))
|
||||
collector.add(make_result(1))
|
||||
|
||||
ordered = collector.get_ordered_results()
|
||||
assert [r.sequence for r in ordered] == [0, 1, 2]
|
||||
|
||||
def test_avg_processing_time(self, make_result):
|
||||
"""Average processing time from sliding window."""
|
||||
collector = ResultCollector(total_chunks=2)
|
||||
collector.add(make_result(0, processing_time=0.1))
|
||||
collector.add(make_result(1, processing_time=0.3))
|
||||
|
||||
assert abs(collector.avg_processing_time - 0.2) < 0.001
|
||||
|
||||
def test_not_complete_when_partial(self, make_result):
|
||||
"""is_complete is False until all chunks emitted."""
|
||||
collector = ResultCollector(total_chunks=3)
|
||||
collector.add(make_result(0))
|
||||
collector.add(make_result(1))
|
||||
assert not collector.is_complete
|
||||
Reference in New Issue
Block a user