Files
xinmi/docreader/tests/test_parser_concurrency.py
T
yawan f7fc992f57
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
2026-09-22 16:19:06 +08:00

89 lines
2.9 KiB
Python

import base64
import io
import threading
import time
import unittest
import uuid
from PIL import Image
from docreader.parser.concurrency import parser_worker_limit
from docreader.parser.pdf_parser import PDFScannedParser, _normalize_image_quality
class ParserConcurrencyTest(unittest.TestCase):
def test_parser_worker_limit_serializes_work(self):
limiter_name = f"test-{uuid.uuid4()}"
active_workers = 0
max_active_workers = 0
state_lock = threading.Lock()
start = threading.Barrier(3)
def worker():
nonlocal active_workers, max_active_workers
start.wait()
with parser_worker_limit(limiter_name, 1):
with state_lock:
active_workers += 1
max_active_workers = max(max_active_workers, active_workers)
time.sleep(0.02)
with state_lock:
active_workers -= 1
threads = [threading.Thread(target=worker) for _ in range(2)]
for thread in threads:
thread.start()
start.wait()
for thread in threads:
thread.join()
self.assertEqual(max_active_workers, 1)
def test_scanned_pdf_parser_outputs_jpeg_images(self):
pdf_bytes = io.BytesIO()
pages = [
Image.new("RGB", (64, 64), "white"),
Image.new("RGB", (64, 64), "black"),
]
pages[0].save(
pdf_bytes,
format="PDF",
save_all=True,
append_images=pages[1:],
)
document = PDFScannedParser(file_name="scan.pdf").parse_into_text(
pdf_bytes.getvalue()
)
image_ref = "images/scan_page_1.jpg"
self.assertIn(f"![scan_page_1.jpg]({image_ref})", document.content)
self.assertIn(image_ref, document.images)
self.assertEqual(document.metadata["image_source_type"], "scanned_pdf")
self.assertEqual(document.metadata["page_count"], 2)
self.assertEqual(len(document.images), 2)
self.assertIn("images/scan_page_2.jpg", document.images)
image_bytes = base64.b64decode(document.images[image_ref])
self.assertTrue(image_bytes.startswith(b"\xff\xd8"))
def test_scanned_pdf_parser_logs_malformed_pdf_without_format_error(self):
parser = PDFScannedParser(file_name="broken.pdf")
with self.assertLogs("docreader.parser.pdf_parser", level="ERROR") as logs:
with self.assertRaises(Exception):
parser.parse_into_text(b"not a pdf")
self.assertTrue(
any("PDFScannedParser failed to parse PDF:" in line for line in logs.output)
)
def test_normalize_image_quality_bounds_jpeg_quality(self):
self.assertEqual(_normalize_image_quality(-1), 1)
self.assertEqual(_normalize_image_quality(90), 90)
self.assertEqual(_normalize_image_quality(120), 95)
if __name__ == "__main__":
unittest.main()