Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

360 lines
11 KiB
Python

"""
Performance tests for citation formatter to ensure it handles large documents efficiently.
"""
import time
import pytest
from local_deep_research.text_optimization.citation_formatter import (
CitationFormatter,
CitationMode,
)
class TestCitationPerformance:
"""Test performance of citation formatter with large documents."""
def test_many_citations_performance(self):
"""Test performance with many citations."""
# Generate content with 1000 citations
citations = []
sources = []
for i in range(1, 1001):
# Mix up citation patterns
if i % 3 == 0:
citations.append(f"Multiple [{i}] citations [{i}] here [{i}]")
else:
citations.append(f"Single citation [{i}]")
sources.append(f"""[{i}] Source {i} Title
URL: https://example{i % 100}.com/paper/{i}""")
content = f"""# Large Document Performance Test
{" ".join(citations)}
## Sources
{chr(10).join(sources)}"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
start_time = time.time()
result = formatter.format_document(content)
end_time = time.time()
processing_time = end_time - start_time
# Should complete in reasonable time (less than 5 seconds for 1000 citations)
assert processing_time < 5.0, (
f"Processing took {processing_time:.2f}s, which is too slow"
)
# Should have formatted all citations
for i in range(100):
assert f"[example{i}.com]" in result
def test_long_document_performance(self):
"""Test performance with very long documents."""
# Create a 100KB document
paragraphs = []
for i in range(200):
paragraph = f"""
This is paragraph {i} with some citations [{i % 50 + 1}] and more text to make
it longer. The citation [{i % 50 + 1}] appears multiple times in this paragraph.
Sometimes we reference [{(i + 1) % 50 + 1}] as well. This helps test performance
with realistic document sizes and citation patterns.
"""
paragraphs.append(paragraph)
# Add sources
sources = []
for i in range(1, 51):
sources.append(f"""[{i}] Academic Paper {i}
URL: https://journal{i % 10}.com/article/{i}""")
content = f"""# Very Long Document
{"".join(paragraphs)}
## Sources
{chr(10).join(sources)}"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_ID_HYPERLINKS)
start_time = time.time()
result = formatter.format_document(content)
end_time = time.time()
processing_time = end_time - start_time
# Should handle large documents efficiently
assert processing_time < 10.0, (
f"Processing took {processing_time:.2f}s for large document"
)
# Verify formatting worked
assert "[journal0.com" in result
assert "[journal9.com" in result
def test_deeply_nested_markdown_performance(self):
"""Test performance with deeply nested markdown structures."""
# Create nested lists with citations
nested_content = """# Document with Nested Structure
"""
for i in range(10):
nested_content += f"{' ' * i}- Level {i} item [{i + 1}]\n"
nested_content += (
f"{' ' * i} - Sub-item with citation [{i + 11}]\n"
)
nested_content += f"{' ' * i} - Deep sub-item [{i + 21}]\n"
# Add complex markdown
nested_content += """
| Header 1 [31] | Header 2 [32] | Header 3 [33] |
|---------------|---------------|---------------|
| Cell [34] | Cell [35] | Cell [36] |
| Cell [37] | Cell [38] | Cell [39] |
> Blockquote level 1 [40]
>> Blockquote level 2 [41]
>>> Blockquote level 3 [42]
"""
# Add sources
sources = []
for i in range(1, 43):
sources.append(
f"[{i}] Source {i}\nURL: https://site{i % 5}.com/{i}"
)
content = nested_content + "\n## Sources\n\n" + "\n\n".join(sources)
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
start_time = time.time()
result = formatter.format_document(content)
end_time = time.time()
processing_time = end_time - start_time
# Should handle complex structure efficiently
assert processing_time < 2.0, (
f"Processing complex structure took {processing_time:.2f}s"
)
# Verify citations in various contexts were formatted
assert "[site0.com]" in result
assert "[site4.com]" in result
def test_repeated_formatting_performance(self):
"""Test performance when formatting the same document multiple times."""
content = """# Document
Citations [1] and [2] and [3].
## Sources
[1] First
URL: https://first.com
[2] Second
URL: https://second.com
[3] Third
URL: https://third.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
# Format 100 times
start_time = time.time()
for _ in range(100):
formatter.format_document(content)
end_time = time.time()
total_time = end_time - start_time
avg_time = total_time / 100
# Average time should be very fast
assert avg_time < 0.01, (
f"Average formatting time {avg_time:.4f}s is too slow"
)
def test_citation_modes_performance_comparison(self):
"""Compare performance across different citation modes."""
# Create test document
citations = [f"Citation [{i}]" for i in range(1, 101)]
sources = [
f"[{i}] Source {i}\nURL: https://domain{i % 20}.com/{i}"
for i in range(1, 101)
]
content = f"""# Performance Test
{" ".join(citations)}
## Sources
{chr(10).join(sources)}"""
modes = [
CitationMode.NUMBER_HYPERLINKS,
CitationMode.DOMAIN_HYPERLINKS,
CitationMode.DOMAIN_ID_HYPERLINKS,
CitationMode.DOMAIN_ID_ALWAYS_HYPERLINKS,
CitationMode.NO_HYPERLINKS,
]
times = {}
for mode in modes:
formatter = CitationFormatter(mode=mode)
start_time = time.time()
formatter.format_document(content)
end_time = time.time()
times[mode.value] = end_time - start_time
# All modes should complete quickly
for mode_name, duration in times.items():
assert duration < 1.0, f"Mode {mode_name} took {duration:.3f}s"
# Performance shouldn't vary drastically between modes
# Exclude NO_HYPERLINKS from comparison as it does minimal processing
times_without_no_hyperlinks = {
k: v for k, v in times.items() if k != "no_hyperlinks"
}
if times_without_no_hyperlinks:
max_time = max(times_without_no_hyperlinks.values())
min_time = min(times_without_no_hyperlinks.values())
# Allow more variance as some modes do more work
if min_time > 0:
assert max_time / min_time < 10.0, (
f"Performance varies too much between modes (excluding no_hyperlinks): {times_without_no_hyperlinks}"
)
# Verify NO_HYPERLINKS is indeed the fastest
if "no_hyperlinks" in times:
no_hyperlinks_time = times["no_hyperlinks"]
other_times = [v for k, v in times.items() if k != "no_hyperlinks"]
if other_times:
# NO_HYPERLINKS should be faster or comparable to the fastest other mode
assert no_hyperlinks_time <= min(other_times) * 2, (
"NO_HYPERLINKS mode should be among the fastest modes"
)
def test_memory_efficiency_large_content(self):
"""Test that formatter doesn't use excessive memory."""
# Create a large document (10MB+)
large_text = "This is a test paragraph. " * 10000
content = f"""# Large Document
{large_text}
Citation at the end [1].
## Sources
[1] Only Source
URL: https://example.com/source"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
# Should handle large content without issues
try:
start_time = time.time()
result = formatter.format_document(content)
end_time = time.time()
# Should complete even with large content
assert "[example.com]" in result
assert end_time - start_time < 5.0
except MemoryError:
pytest.fail("Formatter used too much memory")
@pytest.mark.parametrize("num_sources", [10, 50, 100, 500])
def test_scaling_with_source_count(self, num_sources):
"""Test how performance scales with number of sources."""
# Create content with varying number of sources
citations = []
sources = []
# Each source cited 3 times
for i in range(1, num_sources + 1):
citations.extend([f"[{i}]", f"[{i}]", f"[{i}]"])
sources.append(f"[{i}] Source {i}\nURL: https://example.com/{i}")
content = f"""# Scaling Test
Citations: {" ".join(citations)}
## Sources
{chr(10).join(sources)}"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_ID_HYPERLINKS)
start_time = time.time()
formatter.format_document(content)
end_time = time.time()
processing_time = end_time - start_time
# Time should scale roughly linearly with source count
expected_max_time = num_sources * 0.01 # 10ms per source max
assert processing_time < expected_max_time, (
f"Processing {num_sources} sources took {processing_time:.3f}s, "
f"expected < {expected_max_time:.3f}s"
)
def test_regex_performance_edge_cases(self):
"""Test performance with content that might cause regex issues."""
# Create content with patterns that could cause backtracking
tricky_patterns = [
"[" * 100 + "1" + "]" * 100, # Many brackets
"[[[[1]]]]", # Nested brackets
"[1][2][3][4][5]" * 50, # Many consecutive citations
"[1] " + "." * 1000 + " [2]", # Long spans between citations
]
sources = """
[1] Source 1
URL: https://one.com
[2] Source 2
URL: https://two.com
[3] Source 3
URL: https://three.com
[4] Source 4
URL: https://four.com
[5] Source 5
URL: https://five.com"""
for pattern in tricky_patterns:
content = f"# Test\n\n{pattern}\n\n## Sources\n{sources}"
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
start_time = time.time()
try:
formatter.format_document(content)
end_time = time.time()
# Should complete quickly even with tricky patterns
assert end_time - start_time < 1.0
except Exception as e:
pytest.fail(f"Failed on pattern: {pattern[:50]}... Error: {e}")