1+ import os
2+ import pytest
3+ from unittest .mock import MagicMock , patch
4+
5+ from transformer_engine .plugin .core .types import BackendImplKind , OpImpl
6+ from transformer_engine .plugin .core .policy import SelectionPolicy
7+ from transformer_engine .plugin .core .registry import OpRegistry
8+ from transformer_engine .plugin .core .manager import (
9+ OpManager ,
10+ get_default_manager ,
11+ reset_default_manager ,
12+ )
13+
14+
15+ # ==============================================================================
16+ # Fixtures & Mock Component Factories
17+ # ==============================================================================
18+
19+ @pytest .fixture (autouse = True )
20+ def clean_manager_singleton ():
21+ """Ensure a freshly cleared manager instance before and after each test."""
22+ reset_default_manager ()
23+ yield
24+ reset_default_manager ()
25+
26+
27+ def create_mock_impl (impl_id , kind , op_name = "test_op" , fn = None , priority = 1 , vendor = None ):
28+ """
29+ Factory to generate fully structured OpImpl instances for control injection.
30+ Ensures that VENDOR kinds satisfy internal post-init constraint validations.
31+ """
32+ mock_fn = fn or MagicMock (return_value = f"res_{ impl_id } " )
33+
34+ # Satisfy __post_init__ requirement: VENDOR kind must specify a vendor name
35+ if kind == BackendImplKind .VENDOR and not vendor :
36+ vendor = "nvidia"
37+
38+ impl = OpImpl (
39+ op_name = op_name ,
40+ impl_id = impl_id ,
41+ kind = kind ,
42+ fn = mock_fn ,
43+ priority = priority ,
44+ vendor = vendor
45+ )
46+ return impl
47+
48+
49+ # ==============================================================================
50+ # Part 1: Initialization, Fork Safety & Global Singleton Management
51+ # ==============================================================================
52+
53+ def test_manager_singleton_lifecycle ():
54+ """Verify singleton access, reset primitives, and Windows register_at_fork guards."""
55+ mgr1 = get_default_manager ()
56+ mgr2 = get_default_manager ()
57+ assert mgr1 is mgr2
58+
59+ # Force error branch covering missing register_at_fork (e.g. Windows platforms)
60+ with patch ("os.register_at_fork" , side_effect = AttributeError ):
61+ custom_mgr = OpManager ()
62+ assert custom_mgr is not None
63+
64+
65+ def test_lazy_initialization_flow ():
66+ """Trigger ensure_initialized, checking registry synchronization and tracking logs."""
67+ mock_registry = OpRegistry ()
68+ mgr = OpManager (registry = mock_registry )
69+
70+ assert mgr .registry is mock_registry
71+
72+ mgr .ensure_initialized ()
73+ assert mgr ._state .initialized is True
74+ assert mgr ._state .init_pid == os .getpid ()
75+
76+ mgr .ensure_initialized ()
77+
78+
79+ def test_process_fork_invalidation_handling ():
80+ """Force execute _reset_after_fork to clear transient states and step up policy epochs."""
81+ mgr = OpManager ()
82+ mgr .ensure_initialized ()
83+
84+ mgr ._dispatch_cache [("op" , "fp" , 0 )] = lambda : None
85+ mgr ._impl_cache ["op" ] = MagicMock ()
86+
87+ mgr ._reset_after_fork ()
88+
89+ assert mgr ._state .initialized is False
90+ assert mgr ._state .init_pid == - 1
91+ assert len (mgr ._dispatch_cache ) == 0
92+ assert len (mgr ._impl_cache ) == 0
93+
94+
95+ # ==============================================================================
96+ # Part 2: Vendor Whitelist/Blacklist Filtering Engine
97+ # ==============================================================================
98+
99+ def test_vendor_policy_filter_matching ():
100+ """Trigger _matches_vendor_filters evaluating valid, blocked, and non-vendor impls."""
101+ mgr = OpManager ()
102+
103+ non_vendor_impl = create_mock_impl ("ref" , BackendImplKind .REFERENCE )
104+ nvidia_impl = create_mock_impl ("nv" , BackendImplKind .VENDOR , vendor = "nvidia" )
105+ amd_impl = create_mock_impl ("amd" , BackendImplKind .VENDOR , vendor = "amd" )
106+
107+ # Manually instantiate a VENDOR bypass to simulate missing vendor string if allowed by logic
108+ # Direct instantiation bypassed since it would hit __post_init__ error otherwise
109+ with patch .object (OpImpl , "__post_init__" , return_value = None ):
110+ vendor_no_name = OpImpl (
111+ op_name = "test_op" ,
112+ impl_id = "vend_none" ,
113+ kind = BackendImplKind .VENDOR ,
114+ fn = MagicMock (),
115+ priority = 1 ,
116+ vendor = None
117+ )
118+
119+ # Scenario 1: Deny List Filtering
120+ policy_deny = SelectionPolicy .from_dict (deny_vendors = {"amd" })
121+ assert mgr ._matches_vendor_filters (non_vendor_impl , policy_deny ) is True
122+ assert mgr ._matches_vendor_filters (vendor_no_name , policy_deny ) is False
123+ assert mgr ._matches_vendor_filters (nvidia_impl , policy_deny ) is True
124+ assert mgr ._matches_vendor_filters (amd_impl , policy_deny ) is False
125+
126+ # Scenario 2: Allow Whitelist Filtering
127+ policy_allow = SelectionPolicy .from_dict (allow_vendors = {"nvidia" })
128+ assert mgr ._matches_vendor_filters (nvidia_impl , policy_allow ) is True
129+ assert mgr ._matches_vendor_filters (amd_impl , policy_allow ) is False
130+
131+
132+ # ==============================================================================
133+ # Part 3: Resolver Pipelines and Resolution Error Fallbacks
134+ # ==============================================================================
135+
136+ def test_resolve_with_cache_and_priority ():
137+ """Test operational resolve pathways, cache hits, priority sorting and empty states."""
138+ mock_registry = OpRegistry ()
139+ mgr = OpManager (registry = mock_registry )
140+
141+ impl_low = create_mock_impl ("v1" , BackendImplKind .VENDOR , op_name = "test_op" , priority = 1 , vendor = "nvidia" )
142+ impl_high = create_mock_impl ("v2" , BackendImplKind .VENDOR , op_name = "test_op" , priority = 10 , vendor = "nvidia" )
143+
144+ mock_registry .register_impl (impl_low )
145+ mock_registry .register_impl (impl_high )
146+
147+ # Safe patch of object method on frozen dataclasses to return True
148+ with patch .object (OpImpl , "is_available" , return_value = True ):
149+ selected_fn = mgr .resolve ("test_op" )
150+ assert selected_fn == impl_high .fn
151+ assert mgr .get_selected_impl_id ("test_op" ) == "v2"
152+ assert mgr .resolve ("test_op" ) == selected_fn
153+
154+
155+ def test_resolution_failures_and_strict_modes ():
156+ """Provoke exception blocks when operators are missing or filtered out."""
157+ mock_registry = OpRegistry ()
158+ mgr = OpManager (registry = mock_registry )
159+
160+ # nonexistent operator
161+ with pytest .raises (RuntimeError , match = "No available implementation" ):
162+ mgr .resolve ("ghost_op" )
163+
164+ with pytest .raises (RuntimeError , match = "No available implementation" ):
165+ mgr .resolve_candidates ("ghost_op" )
166+
167+ # availability check failure
168+ broken_impl = create_mock_impl (
169+ "broken" ,
170+ BackendImplKind .REFERENCE ,
171+ op_name = "broken_op" ,
172+ )
173+ mock_registry .register_impl (broken_impl )
174+
175+ with patch .object (
176+ OpImpl ,
177+ "is_available" ,
178+ side_effect = Exception ("HW Missing" ),
179+ ):
180+ with pytest .raises (RuntimeError , match = "No available implementation" ):
181+ mgr .resolve ("broken_op" )
182+
183+ # vendor policy filters out all candidates
184+ amd_impl = create_mock_impl (
185+ "amd_impl" ,
186+ BackendImplKind .VENDOR ,
187+ op_name = "strict_op" ,
188+ vendor = "amd" ,
189+ )
190+
191+ mock_registry .register_impl (amd_impl )
192+
193+ policy = SelectionPolicy .from_dict (
194+ allow_vendors = {"nvidia" },
195+ strict = True ,
196+ )
197+
198+ with patch (
199+ "transformer_engine.plugin.core.manager.get_policy" ,
200+ return_value = policy ,
201+ ):
202+ with patch .object (OpImpl , "is_available" , return_value = True ):
203+ with pytest .raises (
204+ RuntimeError ,
205+ match = "No available implementation" ,
206+ ):
207+ mgr .resolve ("strict_op" )
208+
209+
210+ # ==============================================================================
211+ # Part 4: High-Level Core Dispatch Invokers (call & fallback)
212+ # ==============================================================================
213+
214+ def test_call_with_fallback_and_invalidation ():
215+ """Route execution patterns through standard invoke, caching, errors, and fallbacks."""
216+
217+ # ------------------------------------------------------------------
218+ # Case 1:
219+ # vendor implementation fails
220+ # reference implementation succeeds (fallback path)
221+ # ------------------------------------------------------------------
222+ registry = OpRegistry ()
223+ mgr = OpManager (registry = registry )
224+
225+ primary_impl = create_mock_impl (
226+ "v1" ,
227+ BackendImplKind .VENDOR ,
228+ op_name = "fallback_op" ,
229+ vendor = "nvidia" ,
230+ )
231+ primary_impl .fn .side_effect = Exception ("CUDA Out of Memory" )
232+
233+ backup_impl = create_mock_impl (
234+ "ref" ,
235+ BackendImplKind .REFERENCE ,
236+ op_name = "fallback_op" ,
237+ )
238+
239+ registry .register_impl (primary_impl )
240+ registry .register_impl (backup_impl )
241+
242+ with patch .object (OpImpl , "is_available" , return_value = True ):
243+ result = mgr .call ("fallback_op" , 10 , x = 5 )
244+
245+ assert result == "res_ref"
246+
247+ backup_impl .fn .assert_called_once_with (
248+ 10 ,
249+ x = 5 ,
250+ )
251+
252+ assert mgr ._get_last_impl_id ("fallback_op" ) == "ref"
253+
254+ # ------------------------------------------------------------------
255+ # Case 2:
256+ # strict mode (TE_FL_STRICT=0)
257+ # fallback disabled
258+ # vendor implementation failure should propagate directly
259+ # ------------------------------------------------------------------
260+ strict_registry = OpRegistry ()
261+
262+ failing_impl = create_mock_impl (
263+ "strict_vendor" ,
264+ BackendImplKind .VENDOR ,
265+ op_name = "strict_op" ,
266+ vendor = "nvidia" ,
267+ )
268+
269+ failing_impl .fn .side_effect = Exception ("CUDA Out of Memory" )
270+
271+ strict_registry .register_impl (failing_impl )
272+
273+ strict_mgr = OpManager (registry = strict_registry )
274+
275+ with patch ("os.getenv" , return_value = "0" ):
276+ with patch .object (OpImpl , "is_available" , return_value = True ):
277+ with pytest .raises (Exception , match = "CUDA Out of Memory" ):
278+ strict_mgr .call ("strict_op" )
279+
280+ # ==============================================================================
281+ # Part 5: Cache Stability and Helper Primitives
282+ # ==============================================================================
283+
284+ def test_cache_validation_and_epoch_bumps ():
285+ """Cover _is_cache_valid, _update_cache and bump_policy_epoch."""
286+ mgr = OpManager ()
287+
288+ assert mgr ._is_cache_valid ("unknown_op" ) is False
289+
290+ impl = create_mock_impl (
291+ "v1" ,
292+ BackendImplKind .VENDOR ,
293+ op_name = "validated_op" ,
294+ vendor = "nvidia" ,
295+ )
296+
297+ mgr ._update_cache ("validated_op" , impl )
298+
299+ assert mgr ._is_cache_valid ("validated_op" ) is True
300+
301+ mgr .bump_policy_epoch ()
302+
303+ assert mgr ._is_cache_valid ("validated_op" ) is False
304+
305+ assert mgr ._get_last_impl_id ("validated_op" ) == "v1"
306+
307+
308+ def test_get_selected_impl_id ():
309+ """Verify selected impl id lookup through resolve()."""
310+
311+ registry = OpRegistry ()
312+
313+ impl = create_mock_impl (
314+ "v1" ,
315+ BackendImplKind .VENDOR ,
316+ op_name = "validated_op" ,
317+ vendor = "nvidia" ,
318+ )
319+
320+ registry .register_impl (impl )
321+
322+ mgr = OpManager (registry = registry )
323+
324+ with patch .object (mgr , "ensure_initialized" ):
325+ with patch .object (OpImpl , "is_available" , return_value = True ):
326+ assert mgr .get_selected_impl_id ("validated_op" ) == "v1"
0 commit comments