1+ using System . Collections . Generic ;
2+ using System . ComponentModel . DataAnnotations ;
3+ using System . Threading . Tasks ;
4+ using RecursiveDataAnnotationsValidation . Tests . TestModels ;
5+ using Xunit ;
6+
7+ namespace RecursiveDataAnnotationsValidation . Tests
8+ {
9+ public class DeadlockPreventionTests
10+ {
11+ private readonly IAsyncRecursiveDataAnnotationValidator _sut = new RecursiveDataAnnotationValidator ( ) ;
12+
13+ /// <summary>
14+ /// Test to ensure that our async implementation doesn't create potential deadlocks
15+ /// by testing proper async execution patterns.
16+ /// </summary>
17+ [ Fact ]
18+ public async Task Async_methods_should_not_create_deadlocks ( )
19+ {
20+ // This test ensures that the async methods properly execute
21+ // without creating synchronization context issues that could lead to deadlocks
22+
23+ var model = new SimpleExample
24+ {
25+ IntegerA = 100 ,
26+ StringB = "test-100" ,
27+ BoolC = true ,
28+ ExampleEnumD = ExampleEnum . ValueB
29+ } ;
30+
31+ var validationResults = new List < ValidationResult > ( ) ;
32+
33+ // Test that the async method can be awaited without blocking
34+ var result = await _sut . TryValidateObjectRecursiveAsync ( model , validationResults ) ;
35+
36+ Assert . True ( result ) ;
37+ Assert . Empty ( validationResults ) ;
38+ }
39+
40+ /// <summary>
41+ /// Test that validates async behavior with collections doesn't cause blocking issues
42+ /// </summary>
43+ [ Fact ]
44+ public async Task Async_collection_validation_should_not_deadlock ( )
45+ {
46+ var model = new ItemWithListExample
47+ {
48+ ItemWithListName = "Parent" ,
49+ Claims = new List < string > { "Claim1" , "Claim2" }
50+ } ;
51+
52+ var validationResults = new List < ValidationResult > ( ) ;
53+
54+ // Test that collection validation works async without hanging
55+ var result = await _sut . TryValidateObjectRecursiveAsync ( model , validationResults ) ;
56+
57+ Assert . True ( result ) ;
58+ Assert . Empty ( validationResults ) ;
59+ }
60+
61+ /// <summary>
62+ /// Test that validates recursive structure handling async without deadlock
63+ /// </summary>
64+ [ Fact ]
65+ public async Task Async_recursive_validation_should_not_deadlock ( )
66+ {
67+ var recursiveModel = new RecursionExample
68+ {
69+ Name = "Recursion1-pass" ,
70+ BooleanA = false ,
71+ Recursion = new RecursionExample
72+ {
73+ Name = "Recursion1-pass.Inner1" ,
74+ BooleanA = true ,
75+ Recursion = null
76+ }
77+ } ;
78+ recursiveModel . Recursion . Recursion = recursiveModel ;
79+
80+ var model = new RecursionExample
81+ {
82+ Name = "SUT" ,
83+ BooleanA = true ,
84+ Recursion = recursiveModel
85+ } ;
86+
87+ var validationResults = new List < ValidationResult > ( ) ;
88+
89+ // Test that recursive validation works async without hanging
90+ var result = await _sut . TryValidateObjectRecursiveAsync ( model , validationResults ) ;
91+
92+ Assert . True ( result ) ;
93+ Assert . Empty ( validationResults ) ;
94+ }
95+
96+ /// <summary>
97+ /// Test that the async methods properly handle validation errors without deadlocking
98+ /// </summary>
99+ [ Fact ]
100+ public async Task Async_error_handling_should_not_deadlock ( )
101+ {
102+ var model = new SimpleExample
103+ {
104+ IntegerA = null , // This should fail validation due to [Required]
105+ StringB = "test-101" ,
106+ BoolC = false ,
107+ ExampleEnumD = ExampleEnum . ValueC
108+ } ;
109+
110+ var validationResults = new List < ValidationResult > ( ) ;
111+
112+ // Test that error handling works async without hanging
113+ var result = await _sut . TryValidateObjectRecursiveAsync ( model , validationResults ) ;
114+
115+ Assert . False ( result ) ;
116+ Assert . NotEmpty ( validationResults ) ;
117+ }
118+
119+ /// <summary>
120+ /// Test that validates proper async execution pattern for concurrent usage
121+ /// </summary>
122+ [ Fact ]
123+ public async Task Multiple_concurrent_async_calls_should_not_deadlock ( )
124+ {
125+ var model1 = new SimpleExample
126+ {
127+ IntegerA = 100 ,
128+ StringB = "test-100" ,
129+ BoolC = true ,
130+ ExampleEnumD = ExampleEnum . ValueB
131+ } ;
132+
133+ var model2 = new SimpleExample
134+ {
135+ IntegerA = 200 ,
136+ StringB = "test-200" ,
137+ BoolC = false ,
138+ ExampleEnumD = ExampleEnum . ValueA
139+ } ;
140+
141+ var validationResults1 = new List < ValidationResult > ( ) ;
142+ var validationResults2 = new List < ValidationResult > ( ) ;
143+
144+ // Test concurrent async calls
145+ var task1 = _sut . TryValidateObjectRecursiveAsync ( model1 , validationResults1 ) ;
146+ var task2 = _sut . TryValidateObjectRecursiveAsync ( model2 , validationResults2 ) ;
147+
148+ // Both should complete without deadlocking
149+ var results = await Task . WhenAll ( task1 , task2 ) ;
150+
151+ Assert . True ( results [ 0 ] ) ;
152+ Assert . True ( results [ 1 ] ) ;
153+ Assert . Empty ( validationResults1 ) ;
154+ Assert . Empty ( validationResults2 ) ;
155+ }
156+ }
157+ }
0 commit comments