From e1b889246a11816746f6fadd62a4ceda9e674999 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Thu, 25 Jan 2024 17:43:14 -0600 Subject: [PATCH] Add a deeply recursive schema/union test This adds a test from [this pydantic issue](https://github.com/pydantic/pydantic/issues/8499) to ensure that we don't error out when processing deeply recursive schemas with unions. No code change is needed at this time, we process this schema efficiently already. --- tests/test_performance.py | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/test_performance.py diff --git a/tests/test_performance.py b/tests/test_performance.py new file mode 100644 index 00000000..86d8b21e --- /dev/null +++ b/tests/test_performance.py @@ -0,0 +1,51 @@ +import textwrap + +import msgspec + +from utils import temp_module + + +def test_process_large_recursive_union(): + """ + A recursive schema processing perf test from + https://github.com/pydantic/pydantic/issues/8499 + + This test is mostly to ensure that processing deeply recursive schemas with + unions succeeds. + """ + + def gen_code(): + yield "from __future__ import annotations" + yield "from msgspec import Struct" + yield "from typing import Union" + + for i in range(50): + yield textwrap.dedent( + f""" + class Node{i}(Struct, tag='node{i}'): + data: Union[Node, None] + """ + ) + yield "Node = Union[" + for i in range(50): + yield f" Node{i}," + yield "]" + + code = "\n".join(gen_code()) + + with temp_module(code) as mod: + dec = msgspec.json.Decoder(mod.Node) + + msg = b""" + { + "type": "node25", + "data": { + "type": "node13", + "data": null + } + } + """ + + sol = mod.Node25(mod.Node13(None)) + + assert dec.decode(msg) == sol