Files
learningcircuit--local-deep…/tests/citation_bugs/test_citation_error_handling.py
T
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

387 lines
9.7 KiB
Python

"""
Tests for citation formatter error handling and malformed input scenarios.
"""
from local_deep_research.text_optimization.citation_formatter import (
CitationFormatter,
CitationMode,
)
class TestCitationErrorHandling:
"""Test error handling and resilience of citation formatter."""
def test_malformed_citation_brackets(self):
"""Test handling of malformed citation brackets."""
content = """# Research Report
Good citation [1], broken citation [2, missing citation ]3[,
reversed [4[ and double [[5]].
## Sources
[1] Good Paper
URL: https://example.com/1
[2] Second Paper
URL: https://example.com/2
[3] Third Paper
URL: https://example.com/3
[4] Fourth Paper
URL: https://example.com/4
[5] Fifth Paper
URL: https://example.com/5"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Good citations should be formatted
assert "[example.com]" in result
# Malformed citations should be left as-is
assert "[2," in result # Broken bracket
assert "]3[" in result # Reversed brackets
assert "[4[" in result # Double opening
def test_invalid_citation_numbers(self):
"""Test handling of invalid citation numbers."""
content = """# Research Report
Valid [1], invalid [0], [999], [-1], [abc], [1.5], [ 2 ].
## Sources
[1] Only Valid Source
URL: https://example.com/valid
[2] Second Source
URL: https://example.com/2"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Valid citation should be formatted
assert "[[example.com]](https://example.com/valid)" in result
# Invalid citations should remain
assert "[0]" in result
assert "[999]" in result
assert "[-1]" in result
assert "[abc]" in result
assert "[1.5]" in result
# Citation with spaces might be processed
# [ 2 ] with spaces is an edge case - formatter might or might not handle it
def test_circular_and_self_referencing(self):
"""Test handling of circular references in sources."""
content = """# Research Report
Citation [1] refers to [2].
## Sources
[1] First Paper [2]
URL: https://first.com
[2] Second Paper [1]
URL: https://second.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Should format main text citations
assert "[first.com]" in result
assert "[second.com]" in result
# Should not format citations within source descriptions
sources_section = result.split("## Sources")[1]
assert "[1] First Paper [2]" in sources_section
assert "[2] Second Paper [1]" in sources_section
def test_missing_source_numbers(self):
"""Test handling when source numbers are missing."""
content = """# Research Report
Citations [1], [2], [3].
## Sources
[1] First Paper
URL: https://first.com
[3] Third Paper (note: [2] is missing)
URL: https://third.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Existing sources should be formatted
assert "[first.com]" in result
assert "[third.com]" in result
# Missing source [2] should remain as-is
assert "[2]" in result
def test_duplicate_source_numbers(self):
"""Test handling of duplicate source numbers."""
content = """# Research Report
Citations [1] and another [1].
## Sources
[1] First Paper
URL: https://first.com
[1] Duplicate Paper
URL: https://duplicate.com
[2] Normal Paper
URL: https://second.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Should handle duplicates (typically takes first occurrence)
# The specific behavior depends on implementation
assert "[first.com]" in result or "[duplicate.com]" in result
def test_sources_without_numbers(self):
"""Test handling of sources without proper numbering."""
content = """# Research Report
Citation [1].
## Sources
[1] Proper Source
URL: https://proper.com
Missing Number Source
URL: https://missing.com
[] Empty Brackets
URL: https://empty.com
[a] Letter Instead
URL: https://letter.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Properly numbered source should work
assert "[proper.com]" in result
# Improperly formatted sources should be ignored
assert "[missing.com]" not in result
assert "[empty.com]" not in result
assert "[letter.com]" not in result
def test_nested_brackets_and_escaping(self):
"""Test handling of nested brackets and escaped characters."""
content = r"""# Research Report
Normal [1], escaped \[2\], nested [[3]], and markdown [link](url) [4].
## Sources
[1] First
URL: https://first.com
[2] Second
URL: https://second.com
[3] Third
URL: https://third.com
[4] Fourth
URL: https://fourth.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Normal citation should work
assert "[first.com]" in result
# Escaped brackets should be preserved
assert r"\[2\]" in result
# Markdown links should not interfere
assert "[link](url)" in result
def test_malformed_urls(self):
"""Test handling of malformed URLs in sources."""
content = """# Research Report
Citations [1] [2] [3] [4] [5].
## Sources
[1] No Protocol
URL: example.com/paper
[2] Invalid Protocol
URL: htp://example.com/paper
[3] Just Domain
URL: https://example.com
[4] Spaces in URL
URL: https://example.com/my paper.pdf
[5] Missing URL Label
https://example.com/nolabel"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Well-formed URLs should work
assert result.count("[example.com]") >= 1
# Malformed URLs might not be processed correctly
# The specific behavior depends on URL parsing implementation
def test_special_markdown_interference(self):
"""Test that special markdown doesn't interfere with citations."""
content = """# Research Report
**Bold [1]**, *italic [2]*, `code [3]`, ~~strike [4]~~.
> Quote [5]
> Multiple lines
| Table | Cell [6] |
|-------|----------|
| Data | [7] |
## Sources
[1] Bold Source
URL: https://bold.com
[2] Italic Source
URL: https://italic.com
[3] Code Source
URL: https://code.com
[4] Strike Source
URL: https://strike.com
[5] Quote Source
URL: https://quote.com
[6] Table Source
URL: https://table.com
[7] Cell Source
URL: https://cell.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# All citations should be formatted despite markdown
domains = [
"bold.com",
"italic.com",
"code.com",
"strike.com",
"quote.com",
"table.com",
"cell.com",
]
for domain in domains:
assert f"[{domain}]" in result
def test_extremely_long_content(self):
"""Test handling of very long documents."""
# Create a document with many citations
citations = []
sources = []
for i in range(1, 101):
citations.append(f"Citation [{i}]")
sources.append(f"""[{i}] Source {i}
URL: https://example{i}.com/paper""")
content = f"""# Large Document
{" ".join(citations)}
## Sources
{chr(10).join(sources)}"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_ID_HYPERLINKS)
result = formatter.format_document(content)
# Should handle all citations
for i in range(1, 101):
assert f"[example{i}.com" in result
def test_source_url_edge_cases(self):
"""Test edge cases in URL detection within sources."""
content = """# Research Report
Citations [1] [2] [3].
## Sources
[1] Multiple URLs
URL: https://first.com
Also available at: https://mirror.com
[2] URL in Middle
Paper Title URL: https://second.com more text
[3] Commented URL
# URL: https://commented.com
URL: https://actual.com"""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Should pick up the first URL after "URL:"
assert "[first.com]" in result
assert "[commented.com]" not in result
# URLs with text after them on the same line are not captured
# This is a known limitation of the current regex pattern
assert "[second.com]" not in result
# URL after a comment line is also not captured
# The formatter only captures URLs immediately after the source title
assert "[actual.com]" not in result
def test_mixed_citation_styles(self):
"""Test documents with mixed citation styles."""
content = """# Research Report
IEEE style [1], parenthetical (Smith, 2023), footnote[^1], and [2].
## Sources
[1] First Paper
URL: https://first.com
[2] Second Paper
URL: https://second.com
[^1]: This is a footnote, not a citation source."""
formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)
result = formatter.format_document(content)
# Should only format numbered citations
assert "[first.com]" in result
assert "[second.com]" in result
# Other citation styles should remain
assert "(Smith, 2023)" in result
assert "[^1]" in result