You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.7 KiB

from fastapi import Depends, FastAPI, Security
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel
app = FastAPI()
counter_holder = {"counter": 0, "parsing_counter": 0}
if PYDANTIC_V2:
from pydantic import model_validator
decorator = model_validator(mode="before")
else:
from pydantic import root_validator
decorator = root_validator
class Model(BaseModel):
@decorator
def __validate__(cls, _):
counter_holder["parsing_counter"] += 1
return {}
async def dep_counter():
counter_holder["counter"] += 1
return counter_holder["counter"]
async def super_dep(count: int = Depends(dep_counter)):
return count
async def model_dep(model: Model) -> Model:
return model
@app.get("/counter/")
async def get_counter(count: int = Depends(dep_counter)):
return {"counter": count}
@app.get("/sub-counter/")
async def get_sub_counter(
subcount: int = Depends(super_dep), count: int = Depends(dep_counter)
):
return {"counter": count, "subcounter": subcount}
@app.get("/sub-counter-no-cache/")
async def get_sub_counter_no_cache(
subcount: int = Depends(super_dep),
count: int = Depends(dep_counter, use_cache=False),
):
return {"counter": count, "subcounter": subcount}
@app.post("/sub-model-parsing/")
async def get_double_model_parsing(
a: Model = Depends(model_dep),
b: Model = Depends(model_dep),
):
assert a is b
return {"parsing_counter": counter_holder["parsing_counter"]}
@app.get("/scope-counter")
async def get_scope_counter(
count: int = Security(dep_counter),
scope_count_1: int = Security(dep_counter, scopes=["scope"]),
scope_count_2: int = Security(dep_counter, scopes=["scope"]),
):
return {
"counter": count,
"scope_counter_1": scope_count_1,
"scope_counter_2": scope_count_2,
}
client = TestClient(app)
def test_normal_counter():
counter_holder["counter"] = 0
response = client.get("/counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 1}
response = client.get("/counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 2}
def test_sub_counter():
counter_holder["counter"] = 0
response = client.get("/sub-counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 1, "subcounter": 1}
response = client.get("/sub-counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 2, "subcounter": 2}
def test_sub_counter_no_cache():
counter_holder["counter"] = 0
response = client.get("/sub-counter-no-cache/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 2, "subcounter": 1}
response = client.get("/sub-counter-no-cache/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 4, "subcounter": 3}
def test_sub_model_parsing_no_repeatable_parsing():
counter_holder["parsing_counter"] = 0
response = client.post("/sub-model-parsing/", json={})
assert response.status_code == 200, response.text
assert response.json() == {"parsing_counter": 1}
def test_security_cache():
counter_holder["counter"] = 0
response = client.get("/scope-counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 1, "scope_counter_1": 2, "scope_counter_2": 2}
response = client.get("/scope-counter/")
assert response.status_code == 200, response.text
assert response.json() == {"counter": 3, "scope_counter_1": 4, "scope_counter_2": 4}