diff --git a/app.py b/app.py index a2d2561..5251c5a 100644 --- a/app.py +++ b/app.py @@ -1,3 +1,5 @@ +import itertools + from flask import Flask, jsonify, request from datetime import datetime, timezone @@ -27,7 +29,7 @@ def create_item(): return jsonify(error="name is required"), 400 item = { - "id": len(_get_items()) + 1, + "id": _new_id(), "name": data["name"], "done": False, } @@ -63,6 +65,11 @@ def delete_item(item_id): _items_store = [] +_id_counter = itertools.count(1) + + +def _new_id(): + return next(_id_counter) def _get_items(): @@ -71,7 +78,9 @@ def _get_items(): def reset_items(): """Reset the in-memory store (used by tests).""" + global _id_counter _items_store.clear() + _id_counter = itertools.count(1) if __name__ == "__main__": diff --git a/test_app.py b/test_app.py index d5ae8f6..29f29a6 100644 --- a/test_app.py +++ b/test_app.py @@ -63,3 +63,48 @@ def test_delete_item(client): def test_delete_item_not_found(client): resp = client.delete("/items/999") assert resp.status_code == 404 + + +def test_no_id_collision_after_delete(client): + """IDs must never be reused after deletion.""" + resp1 = client.post("/items", json={"name": "A"}) + resp2 = client.post("/items", json={"name": "B"}) + id_a = resp1.get_json()["id"] + id_b = resp2.get_json()["id"] + + # Delete first item + client.delete(f"/items/{id_a}") + + # Create a new item — should NOT collide with B's id + resp3 = client.post("/items", json={"name": "C"}) + id_c = resp3.get_json()["id"] + assert id_c != id_b, "New item ID collides with existing item" + + # Verify both remaining items exist in the list + all_items = client.get("/items").get_json()["items"] + all_ids = [item["id"] for item in all_items] + assert id_b in all_ids + assert id_c in all_ids + assert len(all_items) == 2 + + +def test_no_id_reuse_after_multiple_deletes(client): + """IDs stay unique after several deletions followed by several creates.""" + # Create three items + ids = [] + for name in ("X", "Y", "Z"): + resp = client.post("/items", json={"name": name}) + ids.append(resp.get_json()["id"]) + + # Delete all three + for item_id in ids: + client.delete(f"/items/{item_id}") + + # Create two more items — their IDs must not collide with any prior ID + new_ids = [] + for name in ("P", "Q"): + resp = client.post("/items", json={"name": name}) + new_ids.append(resp.get_json()["id"]) + + all_assigned = ids + new_ids + assert len(all_assigned) == len(set(all_assigned)), "ID reuse detected"