import io
import gc
import pytest
from mrrc import MARCReader, MARCWriter
class TestQueueCapacityTracking:
def test_queue_capacity_increases_on_batch_read(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i, record in enumerate(reader):
records.append(record)
if i >= 99: break
assert len(records) == 100
def test_queue_capacity_decreases_on_pop(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = list(reader)
assert len(records) == 1000
def test_queue_empty_at_eof(self, fixture_small):
reader = MARCReader(io.BytesIO(fixture_small))
list(reader)
with pytest.raises(StopIteration):
next(reader)
class TestBatchSizeHardLimits:
def test_batch_does_not_exceed_200_records(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i in range(200):
records.append(next(reader))
for i in range(200):
records.append(next(reader))
assert len(records) == 400
def test_batch_respects_300kb_limit(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = list(reader)
assert len(records) == 1000
class TestSmallVecMemoryBehavior:
def test_small_record_uses_inline_buffer(self):
assert True
def test_large_record_heap_allocation(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = list(reader)
assert len(records) == 1000
assert len(records) == 1000
def test_record_bytes_preserve_large_content(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = list(reader)
for record in records:
leader = record.leader()
assert leader is not None
class TestMemoryLeakPrevention:
def test_no_leak_on_full_iteration(self, fixture_10k):
reader = MARCReader(io.BytesIO(fixture_10k))
gc.collect()
count = 0
for record in reader:
count += 1
assert count == 10000
gc.collect()
def test_no_leak_on_early_termination(self, fixture_10k):
reader = MARCReader(io.BytesIO(fixture_10k))
gc.collect()
count = 0
for record in reader:
count += 1
if count >= 100:
break
del reader
gc.collect()
def test_no_leak_on_eof_repeated_calls(self, fixture_small):
reader = MARCReader(io.BytesIO(fixture_small))
gc.collect()
list(reader)
for _ in range(100):
try:
next(reader)
except StopIteration:
pass
del reader
gc.collect()
class TestBoundsOnMalformedInput:
def test_empty_file_no_crash(self):
reader = MARCReader(io.BytesIO(b""))
records = list(reader)
assert len(records) == 0
def test_incomplete_record_header(self):
reader = MARCReader(io.BytesIO(b"01"))
error_count = 0
try:
for record in reader:
pass
except Exception:
error_count += 1
assert error_count > 0
def test_truncated_file_mid_record(self, fixture_small):
data = fixture_small
truncated = data[:len(data)//2]
reader = MARCReader(io.BytesIO(truncated))
records = []
error_count = 0
try:
for record in reader:
records.append(record)
except Exception:
error_count += 1
assert True
class TestCapacityTrackingCorrectness:
def test_capacity_tracking_sanity(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = list(reader)
assert len(records) == 1000
class TestBatchSizeBoundaryConditions:
def test_batch_boundary_1_record(self, fixture_small):
reader = MARCReader(io.BytesIO(fixture_small))
rec = next(reader)
output = io.BytesIO()
writer = MARCWriter(output)
writer.write_record(rec)
writer.close()
single_rec_file = output.getvalue()
reader2 = MARCReader(io.BytesIO(single_rec_file))
records = list(reader2)
assert len(records) == 1
def test_batch_boundary_exact_100(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i, rec in enumerate(reader):
records.append(rec)
if i >= 99:
break
assert len(records) == 100
def test_batch_boundary_101(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i, rec in enumerate(reader):
records.append(rec)
if i >= 100:
break
assert len(records) == 101
def test_batch_boundary_200(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i, rec in enumerate(reader):
records.append(rec)
if i >= 199:
break
assert len(records) == 200
def test_batch_boundary_201(self, fixture_1k):
reader = MARCReader(io.BytesIO(fixture_1k))
records = []
for i, rec in enumerate(reader):
records.append(rec)
if i >= 200:
break
assert len(records) == 201
class TestMemoryConsistencyUnderLoad:
def test_10k_records_completes(self, fixture_10k):
reader = MARCReader(io.BytesIO(fixture_10k))
count = 0
for record in reader:
count += 1
assert count == 10000
def test_memory_stable_in_loop(self, fixture_10k):
reader = MARCReader(io.BytesIO(fixture_10k))
records = list(reader)
assert len(records) == 10000