1+ # ═══════════════════════════════════════════════════════════════════════════════
2+ # Tests: Type_Safe Fast Create - Created and Cached
3+ # These tests verify MECHANISM - they FAIL without Type_Safe wiring in place
4+ # ═══════════════════════════════════════════════════════════════════════════════
5+ #
6+ # PURPOSE: Verify that fast_create is ACTUALLY BEING USED by checking:
7+ # - Schema cache is populated after creation
8+ # - Schema cache is NOT populated when fast_create=False
9+ # - Cache warming works via creation
10+ # - Nested class schemas are cached recursively
11+ #
12+ # REQUIRES: Type_Safe wiring in place:
13+ # - Type_Safe.__init__ checks config.fast_create and delegates to fast_create
14+ # - Type_Safe.__setattr__ checks config.skip_validation
15+ #
16+ # WITHOUT WIRING: All tests in this file should FAIL (cache never populated)
17+ #
18+ # ═══════════════════════════════════════════════════════════════════════════════
19+
20+ from typing import Dict , List
21+ from unittest import TestCase
22+ from osbot_utils .type_safe .Type_Safe import Type_Safe
23+ from osbot_utils .type_safe .type_safe_core .config .Type_Safe__Config import Type_Safe__Config
24+ from osbot_utils .type_safe .type_safe_core .fast_create .Type_Safe__Fast_Create__Cache import type_safe_fast_create_cache
25+
26+
27+ # ═══════════════════════════════════════════════════════════════════════════════
28+ # Test Classes
29+ # ═══════════════════════════════════════════════════════════════════════════════
30+
31+ class TS__Simple (Type_Safe ):
32+ name : str = ''
33+ count : int = 0
34+ active : bool = False
35+
36+
37+ class TS__With_Collections (Type_Safe ):
38+ name : str = ''
39+ items : List [str ]
40+ data : Dict [str , int ]
41+
42+
43+ class TS__Inner (Type_Safe ):
44+ value : str = ''
45+ count : int = 0
46+
47+
48+ class TS__With_Nested (Type_Safe ):
49+ inner : TS__Inner
50+ name : str = ''
51+
52+
53+ class TS__Deep_Level3 (Type_Safe ):
54+ data : str = ''
55+
56+
57+ class TS__Deep_Level2 (Type_Safe ):
58+ level3 : TS__Deep_Level3
59+ value : int = 0
60+
61+
62+ class TS__Deep_Level1 (Type_Safe ):
63+ level2 : TS__Deep_Level2
64+ name : str = ''
65+
66+
67+ class TS__Deep (Type_Safe ):
68+ level1 : TS__Deep_Level1
69+ count : int = 0
70+
71+
72+ # ═══════════════════════════════════════════════════════════════════════════════
73+ # Test: Created and Cached (Mechanism Verification)
74+ # ═══════════════════════════════════════════════════════════════════════════════
75+
76+ class test_Type_Safe__Fast_Create__created_and_cached (TestCase ):
77+ """
78+ These tests verify that fast_create mechanism is actually being invoked.
79+ They check cache state which only changes when fast_create path is used.
80+
81+ WITHOUT WIRING: All these tests FAIL because cache is never populated.
82+ WITH WIRING: All these tests PASS.
83+ """
84+
85+ def setUp (self ):
86+ type_safe_fast_create_cache .clear_cache ()
87+
88+ # ───────────────────────────────────────────────────────────────────────────
89+ # Basic Cache Population
90+ # ───────────────────────────────────────────────────────────────────────────
91+
92+ def test__fast_create__populates_cache_for_simple_class (self ): # Schema cached on first use
93+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache # Empty before
94+
95+ with Type_Safe__Config (fast_create = True ):
96+ _ = TS__Simple ()
97+
98+ assert TS__Simple in type_safe_fast_create_cache .schema_cache # Cached after
99+
100+ def test__fast_create__populates_cache_for_collections_class (self ): # Collections class cached
101+ assert TS__With_Collections not in type_safe_fast_create_cache .schema_cache
102+
103+ with Type_Safe__Config (fast_create = True ):
104+ _ = TS__With_Collections ()
105+
106+ assert TS__With_Collections in type_safe_fast_create_cache .schema_cache
107+
108+ def test__fast_create__populates_cache_for_nested_class (self ): # Parent class cached
109+ assert TS__With_Nested not in type_safe_fast_create_cache .schema_cache
110+
111+ with Type_Safe__Config (fast_create = True ):
112+ _ = TS__With_Nested ()
113+
114+ assert TS__With_Nested in type_safe_fast_create_cache .schema_cache
115+
116+ # ───────────────────────────────────────────────────────────────────────────
117+ # Recursive Cache Population (Nested Classes)
118+ # ───────────────────────────────────────────────────────────────────────────
119+
120+ def test__fast_create__caches_nested_class_recursively (self ): # Inner class also cached
121+ assert TS__With_Nested not in type_safe_fast_create_cache .schema_cache
122+ assert TS__Inner not in type_safe_fast_create_cache .schema_cache
123+
124+ with Type_Safe__Config (fast_create = True ):
125+ _ = TS__With_Nested ()
126+
127+ assert TS__With_Nested in type_safe_fast_create_cache .schema_cache
128+ assert TS__Inner in type_safe_fast_create_cache .schema_cache # Also cached!
129+
130+ def test__fast_create__caches_deep_nested_classes_recursively (self ): # All levels cached
131+ assert TS__Deep not in type_safe_fast_create_cache .schema_cache
132+ assert TS__Deep_Level1 not in type_safe_fast_create_cache .schema_cache
133+ assert TS__Deep_Level2 not in type_safe_fast_create_cache .schema_cache
134+ assert TS__Deep_Level3 not in type_safe_fast_create_cache .schema_cache
135+
136+ with Type_Safe__Config (fast_create = True ):
137+ _ = TS__Deep ()
138+
139+ assert TS__Deep in type_safe_fast_create_cache .schema_cache # Level 0
140+ assert TS__Deep_Level1 in type_safe_fast_create_cache .schema_cache # Level 1
141+ assert TS__Deep_Level2 in type_safe_fast_create_cache .schema_cache # Level 2
142+ assert TS__Deep_Level3 in type_safe_fast_create_cache .schema_cache # Level 3
143+
144+ # ───────────────────────────────────────────────────────────────────────────
145+ # Cache NOT Populated Without fast_create
146+ # ───────────────────────────────────────────────────────────────────────────
147+
148+ def test__normal_mode__does_not_populate_cache (self ): # Normal creation skips cache
149+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache
150+
151+ _ = TS__Simple () # Normal creation (no config)
152+
153+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache # Still empty!
154+
155+ def test__fast_create_false__does_not_populate_cache (self ): # Explicit False skips cache
156+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache
157+
158+ with Type_Safe__Config (fast_create = False ):
159+ _ = TS__Simple ()
160+
161+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache # Still empty!
162+
163+ # ───────────────────────────────────────────────────────────────────────────
164+ # Multiple Creations Use Same Cached Schema
165+ # ───────────────────────────────────────────────────────────────────────────
166+
167+ def test__fast_create__second_creation_uses_cached_schema (self ): # Cache hit on second create
168+ with Type_Safe__Config (fast_create = True ):
169+ _ = TS__Simple ()
170+
171+ schema_after_first = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
172+ assert schema_after_first is not None
173+
174+ with Type_Safe__Config (fast_create = True ):
175+ _ = TS__Simple ()
176+
177+ schema_after_second = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
178+ assert schema_after_second is schema_after_first # Same instance!
179+
180+ def test__fast_create__batch_creation_uses_same_schema (self ): # All batch objects use same schema
181+ with Type_Safe__Config (fast_create = True ):
182+ _ = TS__Simple ()
183+
184+ schema = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
185+ assert schema is not None
186+
187+ cache_size_after_one = len (type_safe_fast_create_cache .schema_cache )
188+
189+ with Type_Safe__Config (fast_create = True ):
190+ for _ in range (100 ):
191+ _ = TS__Simple ()
192+
193+ # Cache size unchanged - all used same schema
194+ assert len (type_safe_fast_create_cache .schema_cache ) == cache_size_after_one
195+ assert type_safe_fast_create_cache .schema_cache .get (TS__Simple ) is schema
196+
197+ # ───────────────────────────────────────────────────────────────────────────
198+ # Schema Content Verification
199+ # ───────────────────────────────────────────────────────────────────────────
200+
201+ def test__fast_create__cached_schema_has_correct_target_class (self ): # Schema points to right class
202+ with Type_Safe__Config (fast_create = True ):
203+ _ = TS__Simple ()
204+
205+ schema = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
206+ assert schema .target_class is TS__Simple
207+
208+ def test__fast_create__cached_schema_has_correct_fields (self ): # Schema has all fields
209+ with Type_Safe__Config (fast_create = True ):
210+ _ = TS__Simple ()
211+
212+ schema = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
213+ field_names = {f .name for f in schema .fields }
214+
215+ assert 'name' in field_names
216+ assert 'count' in field_names
217+ assert 'active' in field_names
218+
219+ def test__fast_create__cached_schema_has_static_dict (self ): # Schema has pre-built static_dict
220+ with Type_Safe__Config (fast_create = True ):
221+ _ = TS__Simple ()
222+
223+ schema = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
224+
225+ assert 'name' in schema .static_dict
226+ assert 'count' in schema .static_dict
227+ assert 'active' in schema .static_dict
228+ assert schema .static_dict ['name' ] == ''
229+ assert schema .static_dict ['count' ] == 0
230+ assert schema .static_dict ['active' ] is False
231+
232+ def test__fast_create__cached_schema_has_factory_fields (self ): # Collections have factory funcs
233+ with Type_Safe__Config (fast_create = True ):
234+ _ = TS__With_Collections ()
235+
236+ schema = type_safe_fast_create_cache .schema_cache .get (TS__With_Collections )
237+
238+ factory_names = {f .name for f in schema .factory_fields }
239+ assert 'items' in factory_names
240+ assert 'data' in factory_names
241+
242+ def test__fast_create__cached_schema_has_nested_fields (self ): # Nested fields identified
243+ with Type_Safe__Config (fast_create = True ):
244+ _ = TS__With_Nested ()
245+
246+ schema = type_safe_fast_create_cache .schema_cache .get (TS__With_Nested )
247+
248+ assert len (schema .nested_fields ) == 1
249+ assert schema .nested_fields [0 ].name == 'inner'
250+ assert schema .nested_fields [0 ].nested_class is TS__Inner
251+
252+ # ───────────────────────────────────────────────────────────────────────────
253+ # Cache State After Context Exit
254+ # ───────────────────────────────────────────────────────────────────────────
255+
256+ def test__fast_create__cache_persists_after_context_exit (self ): # Cache survives context
257+ with Type_Safe__Config (fast_create = True ):
258+ _ = TS__Simple ()
259+
260+ # Outside context - cache still has schema
261+ assert TS__Simple in type_safe_fast_create_cache .schema_cache
262+
263+ def test__fast_create__cache_persists_across_multiple_contexts (self ): # Cache shared across contexts
264+ with Type_Safe__Config (fast_create = True ):
265+ _ = TS__Simple ()
266+
267+ schema_from_first = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
268+
269+ with Type_Safe__Config (fast_create = True ):
270+ _ = TS__Simple ()
271+
272+ schema_from_second = type_safe_fast_create_cache .schema_cache .get (TS__Simple )
273+
274+ assert schema_from_first is schema_from_second # Same schema object
275+
276+ # ───────────────────────────────────────────────────────────────────────────
277+ # Mixed Usage: Some With fast_create, Some Without
278+ # ───────────────────────────────────────────────────────────────────────────
279+
280+ def test__mixed_usage__fast_create_populates_normal_does_not (self ): # Only fast path caches
281+ # Normal creation - no cache
282+ _ = TS__Simple ()
283+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache
284+
285+ # Fast creation - populates cache
286+ with Type_Safe__Config (fast_create = True ):
287+ _ = TS__With_Collections ()
288+
289+ assert TS__Simple not in type_safe_fast_create_cache .schema_cache # Still not cached
290+ assert TS__With_Collections in type_safe_fast_create_cache .schema_cache # Now cached
291+
292+ def test__mixed_usage__different_classes_cached_independently (self ): # Each class cached separately
293+ with Type_Safe__Config (fast_create = True ):
294+ _ = TS__Simple ()
295+
296+ assert TS__Simple in type_safe_fast_create_cache .schema_cache
297+ assert TS__With_Collections not in type_safe_fast_create_cache .schema_cache
298+
299+ with Type_Safe__Config (fast_create = True ):
300+ _ = TS__With_Collections ()
301+
302+ assert TS__Simple in type_safe_fast_create_cache .schema_cache
303+ assert TS__With_Collections in type_safe_fast_create_cache .schema_cache
0 commit comments