← the record

Audit 3bf991c6e89e

pallets/flask at 36e4a824f3: the project's own tests caught 29 of 40 planted faults, 11 got through, and corral proved 10 of those missing tests by writing a test and running it.

repo
https://github.com/pallets/flask
commit
36e4a824f340fdee7ed50937ba8e7f6bc7d17f81
corral
v1.0.0-rc.11
substrate
workspace
seats
critic: claude-haiku-4-5
mutant-generator: gemini-3.6-flash
test-writer: gemini-3.6-flash
tokens
491.6k in, 7.3k out, 25 calls
started
2026-09-08 15:26 UTC
not audited
153 no-language · 79 gitignored · 27 is-test · 21 test-support — lives in the test tree, never a subject · 20 not-selected · 11 no-paired-test · 2 imported at load time — no test exercises it directly · 1 uncovered — no test executes this file

src/flask/app.py

0.72kill rate, 95% interval 0.57–0.84 (n=40, duplicates counted)
29 of 40caught by the project's tests
11got through
10proven missing tests
language
python
status
needs-review
the tests corral wrote
from datetime import timedelta
from flask.app import _make_timedelta
import pytest
import flask
from flask.app import Flask
import warnings
import werkzeug.serving

def test_make_timedelta_converts_int_to_seconds_corral():
    result = _make_timedelta(10)
    assert result == timedelta(seconds=10)
    assert result != timedelta(days=10)

def test_make_timedelta_with_timedelta_instance():
    td = timedelta(days=1, seconds=3600)
    result = _make_timedelta(td)
    assert result == td
    assert isinstance(result, timedelta)
    assert result is td

def test_cli_runner_passes_extra_kwargs():
    app = flask.Flask("test_app_corral")

    class CustomRunner:
        def __init__(self, app, custom_flag=False):
            self.app = app
            self.custom_flag = custom_flag

    app.test_cli_runner_class = CustomRunner
    runner = app.test_cli_runner(custom_flag=True)
    assert runner.custom_flag is True


def test_cli_runner_default_class_passes_kwargs():
    app = flask.Flask("test_app_corral")
    runner = app.test_cli_runner(mix_stderr=False)
    assert runner.mix_stderr is False

def test_deprecated_subclass_super_dispatch_ctx_corral():
    with pytest.warns(DeprecationWarning):

        class DeprecatedApp(Flask):
            def dispatch_request(self):
                return super().dispatch_request()

    app = DeprecatedApp("test_corral_app")

    @app.route("/")
    def index():
        return "Hello World"

    client = app.test_client()
    rv = client.get("/")
    assert rv.status_code == 200
    assert rv.data == b"Hello World"

def test_add_ctx_deprecated_subclass_super_call_corral():
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", DeprecationWarning)

        class SubclassOldSignatureApp(flask.Flask):
            def handle_exception(self, e):
                return super().handle_exception(e)

    app = SubclassOldSignatureApp("corral_test_app")
    app.config["PROPAGATE_EXCEPTIONS"] = False

    err = RuntimeError("corral test exception")
    with app.test_request_context("/"):
        response = app.handle_exception(err)
        assert response.status_code == 500

def test_app_run_resets_got_first_request_corral(monkeypatch):
    monkeypatch.delenv("FLASK_RUN_FROM_CLI", raising=False)
    monkeypatch.setattr(werkzeug.serving, "run_simple", lambda *args, **kwargs: None)

    app = flask.Flask("test_app_corral")
    app._got_first_request = True

    app.run()

    assert app._got_first_request is False

def test_corral_make_shell_context_includes_g():
    app = flask.Flask("test_app_corral")
    context = app.make_shell_context()
    assert "g" in context
    assert context["g"] is flask.g
    assert context["app"] is app

def test_subclass_deprecated_signature_warning():
    with pytest.warns(
        DeprecationWarning,
        match="The 'handle_http_exception' method now takes 'ctx: AppContext'",
    ):

        class LegacyFlaskSubclass(flask.Flask):
            def handle_http_exception(self, e):
                return super().handle_http_exception(e)

def test_old_signature_subclass_remove_ctx_argument():
    with pytest.warns(DeprecationWarning):

        class OldSignatureApp(flask.Flask):
            def preprocess_request(self):
                return "handled_by_old_preprocess"

    app = OldSignatureApp(__name__)

    @app.route("/")
    def index():
        return "hello"

    client = app.test_client()
    rv = client.get("/")
    assert rv.data == b"handled_by_old_preprocess"

def test_open_instance_resource_mode_and_encoding(tmp_path):
    app = flask.Flask(__name__, instance_path=str(tmp_path))

    # Test text mode with custom encoding
    text_file = tmp_path / "test_text.txt"
    text_content = "Hello, World! 🐍"
    text_file.write_bytes(text_content.encode("utf-16"))

    with app.open_instance_resource("test_text.txt", mode="r", encoding="utf-16") as f:
        assert f.read() == text_content

    # Test binary mode
    bin_file = tmp_path / "test_bin.bin"
    bin_content = b"\x00\x01\x02\x03\xff"
    bin_file.write_bytes(bin_content)

    with app.open_instance_resource("test_bin.bin", mode="rb") as f:
        assert f.read() == bin_content

The faults that got through

A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.

s0/m1 · line 73 proven

- return timedelta(seconds=value)
+ return timedelta(days=value)

s0/m2 · line 74 proven

- if value is None or isinstance(value, timedelta):
+ if value is None:

s5/m1 · line 87 proven

- args = args[1:]
+ pass

s2/m1 · line 99 proven

- args = (app_ctx._get_current_object(),)
+ args = (None,)

s2/m2 · line 101 proven

- args = (app_ctx._get_current_object(), *args)
+ args = args

s3/m4 · line 276 proven

- if method is base_method:
+ if method is not base_method:

s6/m5 · line 462 proven

- if "b" in mode:
+ if "b" not in mode:

s3/m3 · line 627 proven

- rv = {"app": self, "g": g}
+ rv = {"app": self}

s2/m4 · line 747 proven

- # reset the first request information if the development server
- # reset normally.  This makes it possible to restart the server
- # without reloader and that stuff from an interactive shell.
- self._got_first_request = False
+ self._got_first_request = True

s0/m3 · line 823 proven

- return cls(self, **kwargs)  # type: ignore
+ return cls(self)  # type: ignore

s4/m4 · line 1559 unproven

- builder.close()
+ pass