chatbot1-11 Exercise 3: Prove the Simulation Can Fail ======================================================== ex3.py (save in the project root): import asyncio import bot.core as core from bot.core import Bot from bot.providers import FakeProvider from bot.simulate import run_simulation def make(): return Bot(FakeProvider()) async def main(): clean = await run_simulation(make, users=10, steps=80, seed=4) print(f"unmodified bot : {clean.messages} messages, violations = {len(clean.violations)}") original = core.sanitise_fact core.sanitise_fact = lambda text, cfg: text or None # the bug: facts are stored exactly as typed try: mutant = await run_simulation(make, users=10, steps=80, seed=4) finally: core.sanitise_fact = original print(f"mutant (no fact sanitising): {mutant.messages} messages, violations = {len(mutant.violations)}") print(" first:", mutant.violations[0]) kinds = sorted({v.split(': ', 1)[1] for v in mutant.violations}) print(" kinds of violation:", kinds) asyncio.run(main()) Run with: py ex3.py Output: unmodified bot : 810 messages, violations = 0 mutant (no fact sanitising): 810 messages, violations = 13 first: user0: a fact was stored that is multi-line or too long kinds of violation: ['a fact was stored that is multi-line or too long'] WHY THIS WORKS AS AN ANSWER --------------------------- The unmodified bot passes the simulation: 810 messages, including awkward ones such as a 500-character /remember, with no violations. For the mutant, the fact sanitiser in bot.core is replaced by a function that returns the text unchanged, so a /remember of 500 characters is stored as typed (and a multi-line one would be too). The simulation's final check scans the facts table for any note that is multi-line or longer than the limit and reports 13 of them. A test that passes on good code and fails on deliberately broken code is evidence that the test is looking at the right thing; a test that passes on both would be worthless. The original function is restored in a finally block so the mutation cannot leak into anything run afterwards.