2860fb5d18
Security / Dependency review (push) Has been skipped
Scorecard / Scorecard analysis (push) Failing after 0s
Validate / eval (push) Failing after 0s
Security / Dependency audit (push) Failing after 1s
Security / Secret scan (push) Failing after 1s
Validate / tests (push) Failing after 0s
Validate / mcp-tests (push) Failing after 1s
GitHub Actions Security Analysis with zizmor 🌈 / zizmor (push) Failing after 1s
Security / SAST scan (push) Failing after 13m52s
140 lines
4.8 KiB
Python
140 lines
4.8 KiB
Python
"""End-to-end regression test for the 2026-04-22 `Prompting GPT Image 2` bug.
|
|
|
|
Guards the failing run's Resolved-block shape end-to-end: stubs
|
|
`grounding.web_search` to return the OpenAI-only subs that caused the
|
|
original failure, then asserts that `auto_resolve` now returns the widened
|
|
list and emits the expected stderr trace.
|
|
|
|
If this test starts failing after a `scripts/lib/categories.py` edit, either
|
|
the fix regressed or the map intentionally dropped the `ai_image_generation`
|
|
category — update the test deliberately.
|
|
|
|
Fixture reference: `tests/fixtures/prompting-gpt-image-2-resolved-block.md`.
|
|
"""
|
|
|
|
import io
|
|
import unittest
|
|
from contextlib import redirect_stderr
|
|
from unittest.mock import patch
|
|
|
|
from lib import resolve
|
|
|
|
OPENAI_BRAND_SUBREDDIT_RESULTS = [
|
|
{
|
|
"title": "r/OpenAI community hub",
|
|
"snippet": "Discussion at r/ChatGPT and r/singularity about GPT Image 2.",
|
|
"url": "https://reddit.com/r/OpenAI/",
|
|
},
|
|
{
|
|
"title": "r/ChatGPTpromptengineering prompt collection",
|
|
"snippet": "Also see r/artificial for broader AI chatter.",
|
|
"url": "",
|
|
},
|
|
]
|
|
|
|
EMPTY_RESULTS: list[dict] = []
|
|
|
|
|
|
def _fake_websearch(label_to_items: dict[str, list[dict]]):
|
|
def _search(query, date_range, config):
|
|
if "subreddit" in query:
|
|
return label_to_items.get("subreddit", EMPTY_RESULTS), {}
|
|
if "news" in query:
|
|
return label_to_items.get("news", EMPTY_RESULTS), {}
|
|
if "handle" in query:
|
|
return label_to_items.get("x_handle", EMPTY_RESULTS), {}
|
|
if "github" in query:
|
|
return label_to_items.get("github", EMPTY_RESULTS), {}
|
|
return EMPTY_RESULTS, {}
|
|
|
|
return _search
|
|
|
|
|
|
class PromptingGptImage2RegressionGuard(unittest.TestCase):
|
|
"""The named 2026-04-22 failure mode. Resolved block must include peers."""
|
|
|
|
@patch("lib.resolve.grounding.web_search")
|
|
def test_auto_resolve_widens_to_image_gen_peers(self, mock_search):
|
|
mock_search.side_effect = _fake_websearch({
|
|
"subreddit": OPENAI_BRAND_SUBREDDIT_RESULTS,
|
|
})
|
|
|
|
result = resolve.auto_resolve(
|
|
"Prompting GPT Image 2",
|
|
{"BRAVE_API_KEY": "fake"},
|
|
)
|
|
|
|
subs_lower = [s.lower() for s in result["subreddits"]]
|
|
|
|
# Original WebSearch-returned brand subs preserved
|
|
self.assertIn("openai", subs_lower)
|
|
self.assertIn("chatgpt", subs_lower)
|
|
self.assertIn("singularity", subs_lower)
|
|
|
|
# At least three of the image-gen peers were added
|
|
expected_peers = {"stablediffusion", "midjourney", "dalle2", "aiart", "promptengineering"}
|
|
found_peers = expected_peers.intersection(subs_lower)
|
|
self.assertGreaterEqual(
|
|
len(found_peers),
|
|
3,
|
|
f"Expected at least 3 image-gen peer subs, found: {found_peers}. "
|
|
f"Actual subs: {result['subreddits']}",
|
|
)
|
|
|
|
self.assertEqual(result["category"], "ai_image_generation")
|
|
|
|
@patch("lib.resolve.grounding.web_search")
|
|
def test_stderr_contains_category_match_log_line(self, mock_search):
|
|
mock_search.side_effect = _fake_websearch({
|
|
"subreddit": OPENAI_BRAND_SUBREDDIT_RESULTS,
|
|
})
|
|
|
|
buf = io.StringIO()
|
|
with redirect_stderr(buf):
|
|
resolve.auto_resolve(
|
|
"Prompting GPT Image 2",
|
|
{"BRAVE_API_KEY": "fake"},
|
|
)
|
|
|
|
self.assertIn("Matched category=ai_image_generation", buf.getvalue())
|
|
|
|
@patch("lib.resolve.grounding.web_search")
|
|
def test_cap_enforced_end_to_end(self, mock_search):
|
|
# Synthesize a subreddit response with 9 brand subs
|
|
many_subs_items = [
|
|
{"title": f"r/Brand{i}", "snippet": "", "url": ""}
|
|
for i in range(9)
|
|
]
|
|
mock_search.side_effect = _fake_websearch({
|
|
"subreddit": many_subs_items,
|
|
})
|
|
|
|
result = resolve.auto_resolve(
|
|
"Prompting GPT Image 2",
|
|
{"BRAVE_API_KEY": "fake"},
|
|
)
|
|
|
|
self.assertLessEqual(len(result["subreddits"]), resolve.MAX_SUBS)
|
|
# The first WebSearch sub is still present (brand subs never evicted)
|
|
self.assertIn("Brand0", result["subreddits"])
|
|
|
|
@patch("lib.resolve.grounding.web_search")
|
|
def test_uncategorized_topic_does_not_inject_peers(self, mock_search):
|
|
mock_search.side_effect = _fake_websearch({
|
|
"subreddit": [{"title": "r/Kanye is wild", "snippet": "", "url": ""}],
|
|
})
|
|
|
|
buf = io.StringIO()
|
|
with redirect_stderr(buf):
|
|
result = resolve.auto_resolve(
|
|
"Kanye West latest album",
|
|
{"BRAVE_API_KEY": "fake"},
|
|
)
|
|
|
|
self.assertEqual(result["subreddits"], ["Kanye"])
|
|
self.assertIsNone(result["category"])
|
|
self.assertNotIn("Matched category=", buf.getvalue())
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|