1- using Moq ;
1+ using FluentAssertions ;
2+ using Moq ;
23using System . Collections . Generic ;
34using System . Linq . Dynamic . Core . CustomTypeProviders ;
45using System . Linq . Dynamic . Core . Parser ;
56using System . Linq . Expressions ;
7+ using System . Threading . Tasks ;
8+ using System . Threading ;
69using Xunit ;
710
811namespace System . Linq . Dynamic . Core . Tests . Parser ;
@@ -53,4 +56,49 @@ public void DynamicExpressionParser_ParseLambda_WithCustomExpressionPromoter()
5356
5457 _expressionPromoterMock . Verify ( e => e . Promote ( It . IsAny < ConstantExpression > ( ) , typeof ( Guid ) , true , true ) , Times . Once ) ;
5558 }
59+
60+ [ Fact ]
61+ public async Task Promote_Should_Succeed_Even_When_LiteralsCache_Is_Cleaned ( )
62+ {
63+ // Arrange
64+ var parsingConfig = new ParsingConfig ( )
65+ {
66+ ConstantExpressionCacheConfig = new Core . Util . Cache . CacheConfig
67+ {
68+ CleanupFrequency = TimeSpan . FromMilliseconds ( 500 ) , // Run cleanup more often
69+ TimeToLive = TimeSpan . FromMilliseconds ( 500 ) , // Shorten TTL to force expiration
70+ ReturnExpiredItems = false
71+ }
72+ } ;
73+ var constantExpressionHelper = ConstantExpressionHelperFactory . GetInstance ( parsingConfig ) ;
74+ var expressionPromoter = new ExpressionPromoter ( parsingConfig ) ;
75+
76+ double value = 0.40 ;
77+ string text = "0.40" ;
78+ Type targetType = typeof ( decimal ) ;
79+
80+ // Step 1: Add constant to cache
81+ var literalExpression = constantExpressionHelper . CreateLiteral ( value , text ) ;
82+ Assert . NotNull ( literalExpression ) ; // Ensure it was added
83+
84+ // Step 2: Manually trigger cleanup
85+ var cts = new CancellationTokenSource ( 500 ) ;
86+ await Task . Run ( async ( ) =>
87+ {
88+ while ( ! cts . IsCancellationRequested )
89+ {
90+ constantExpressionHelper . TryGetText ( literalExpression , out _ ) ;
91+ await Task . Delay ( 50 ) ; // Give some time for cleanup to be triggered
92+ }
93+ } ) ;
94+
95+ // Ensure some cleanup cycles have passed
96+ await Task . Delay ( 500 ) ; // Allow cache cleanup to happen
97+
98+ // Step 3: Attempt to promote the expression after cleanup
99+ var promotedExpression = expressionPromoter . Promote ( literalExpression , targetType , exact : false , convertExpression : true ) ;
100+
101+ // Assert: Promotion should still work even if the cache was cleaned
102+ promotedExpression . Should ( ) . NotBeNull ( ) ; // Ensure `Promote()` still returns a valid expression
103+ }
56104}
0 commit comments