"""Aggregator of regression tests tied to specific bug-fix commits. Each test here guards against a specific bug that was once shipped. Running just this file gives a one-line-per-bug audit: pytest tests/test_regressions.py -v The test bodies are intentionally small; for the exhaustive behavior of each module, see the topical test files (test_fts_sanitizer.py, test_url_cleanup.py, etc.). This file's job is to make the bug catalog scannable. """ import socket from unittest.mock import patch import pytest import app as app_module import db as db_module import handlers as handlers_module from conftest import patch_dns_fail, patch_dns_ok from db import clean_url from handlers import _sanitize_fts_query, handle_bulk_action def test_6ffd38d_clean_url_preserves_www_when_bare_domain_fails(monkeypatch): """6ffd38d: `clean_url` used to strip `www.` unconditionally; for sites that only serve at `www.`, this produced unreachable clean URLs.""" patch_dns_fail(monkeypatch) assert clean_url("https://www.example.com/page") == "https://www.example.com/page" def test_1bc695f_fts_sanitizer_strips_colon(): """1bc695f: FTS5 colon is a column filter — must not appear in sanitized output.""" assert ":" not in _sanitize_fts_query("title:secret body:exposed") @pytest.mark.parametrize("op", ["AND", "OR", "NOT", "NEAR"]) def test_1bc695f_fts_sanitizer_drops_operator_words(op): """1bc695f: operator words (AND/OR/NOT/NEAR) would be interpreted as FTS5 operators if they landed on the unquoted last token.""" out = _sanitize_fts_query(f"foo {op} bar") # operator itself should not appear in the output tokens = out.replace('"', '').split() assert op not in [t.rstrip("*") for t in tokens] def test_1bc695f_gateway_rejects_oversize_body(): """1bc695f: 16 MiB body-size cap prevents memory-exhaustion DoS.""" from tests.test_gateway_limits import FakeGatewayHandler from gateway import MAX_BODY_SIZE h = FakeGatewayHandler( path="/add", method="POST", headers={"Content-Length": str(MAX_BODY_SIZE + 1)}, ) h._forward("POST") assert h._captured["error"] and h._captured["error"][0] == 413 def test_1bc695f_mesh_rejects_non_whitelisted_paths(): """1bc695f: Reticulum callers are limited to GET /api/sites; CSRF cannot authenticate mesh callers.""" resp = app_module.rns_request_handler( path="/tinyweb", data={"method": "POST", "path": "/add", "query": {}, "body": {}, "gateway_host": ""}, request_id="x", link_id="y", remote_identity=None, requested_at=0, ) assert resp["status"] == 403 def test_1bc695f_pool_returns_clean_connection(temp_db, monkeypatch): """1bc695f: uncommitted transactions on a pooled connection used to leak into the next consumer.""" from db import get_db, return_db db = get_db() db.execute( "INSERT INTO pages (url, title, body) VALUES (?, ?, ?)", ("https://leak.example.com/", "should not persist", "body"), ) return_db(db) # no commit db2 = get_db() try: urls = {r["url"] for r in db2.execute("SELECT url FROM pages").fetchall()} finally: return_db(db2) assert "https://leak.example.com/" not in urls def test_8dffd8c_bulk_delete_requires_confirmation(seeded_db, csrf_session): """8dffd8c: bulk delete without confirmed=1 must render a confirm page instead of deleting — the JS confirm on /pages is a first-line filter only.""" from db import get_db, return_db db = get_db() try: pid = db.execute("SELECT id FROM pages LIMIT 1").fetchone()["id"] count_before = db.execute("SELECT count(*) FROM pages").fetchone()[0] finally: return_db(db) resp = handle_bulk_action({"ids": [str(pid)], "action": ["delete"]}) assert "confirm delete" in resp["body"].lower() db = get_db() try: count_after = db.execute("SELECT count(*) FROM pages").fetchone()[0] finally: return_db(db) assert count_before == count_after, "bulk delete ran without confirmation"