1+ using Moq ;
2+
3+ namespace FeatureOne . Tests ;
4+
5+ [ TestFixture ]
6+ public class BackwardCompatibilityTest
7+ {
8+ [ Test ]
9+ public void Integration_BackwardCompatibility_ExistingFeatures ( )
10+ {
11+ // Arrange - Test that existing feature configurations still work
12+ var mockProvider = new Mock < IStorageProvider > ( ) ;
13+ var oldStyleFeature = new Feature ( new FeatureName ( "LegacyFeature" ) ,
14+ new Toggle ( Operator . Any , new SimpleCondition { IsEnabled = true } ) ) ;
15+
16+ mockProvider . Setup ( p => p . GetByName ( "LegacyFeature" ) ) . Returns ( new [ ] { oldStyleFeature } ) ;
17+
18+ var featureStore = new FeatureStore ( mockProvider . Object ) ;
19+ var features = new Features ( featureStore ) ;
20+
21+ // Act
22+ var result = features . IsEnabled ( "LegacyFeature" ) ;
23+
24+ // Assert
25+ Assert . That ( result , Is . True ) ;
26+
27+ // Also test with claims
28+ var claimsResult = features . IsEnabled ( "LegacyFeature" , new Dictionary < string , string > { { "role" , "user" } } ) ;
29+ Assert . That ( claimsResult , Is . True ) ;
30+ }
31+
32+ [ Test ]
33+ public void Integration_NewFeature_DateRangeCondition ( )
34+ {
35+ // Arrange
36+ var mockProvider = new Mock < IStorageProvider > ( ) ;
37+
38+ // Create a feature with DateRangeCondition
39+ var dateRangeFeature = new Feature ( new FeatureName ( "TimeBasedFeature" ) ,
40+ new Toggle ( Operator . Any , new DateRangeCondition
41+ {
42+ StartDate = DateTime . Now . AddDays ( - 1 ) ,
43+ EndDate = DateTime . Now . AddDays ( 1 )
44+ } ) ) ;
45+
46+ mockProvider . Setup ( p => p . GetByName ( "TimeBasedFeature" ) ) . Returns ( new [ ] { dateRangeFeature } ) ;
47+
48+ var featureStore = new FeatureStore ( mockProvider . Object ) ;
49+ var features = new Features ( featureStore ) ;
50+
51+ // Act
52+ var result = features . IsEnabled ( "TimeBasedFeature" ) ;
53+
54+ // Assert - Should be within date range
55+ Assert . That ( result , Is . True ) ;
56+ }
57+
58+ [ Test ]
59+ public void Integration_SecurityFix_ReDoSProtection ( )
60+ {
61+ // Arrange - Test that the ReDoS fix works in integration
62+ var mockProvider = new Mock < IStorageProvider > ( ) ;
63+
64+ // Create a feature with a regex that would cause ReDoS in old version
65+ var regexFeature = new Feature ( new FeatureName ( "ReDosProtectedFeature" ) ,
66+ new Toggle ( Operator . Any , new RegexCondition
67+ {
68+ Claim = "test" ,
69+ Expression = @"^([a-zA-Z0-9]+)+$" , // Known ReDoS pattern
70+ Timeout = TimeSpan . FromMilliseconds ( 100 )
71+ } ) ) ;
72+
73+ mockProvider . Setup ( p => p . GetByName ( "ReDosProtectedFeature" ) ) . Returns ( new [ ] { regexFeature } ) ;
74+
75+ var featureStore = new FeatureStore ( mockProvider . Object ) ;
76+ var features = new Features ( featureStore ) ;
77+
78+ // Act & Assert - Should not hang and should complete quickly
79+ var startTime = DateTime . Now ;
80+ var result = features . IsEnabled ( "ReDosProtectedFeature" , new Dictionary < string , string > { { "test" , new string ( 'a' , 1000 ) } } ) ;
81+ var endTime = DateTime . Now ;
82+
83+ // Should complete quickly (under 1 second) to prove timeout is working
84+ Assert . That ( ( endTime - startTime ) . TotalMilliseconds , Is . LessThan ( 1000 ) ) ;
85+ // The result may vary depending on implementation, but the important thing is no hang
86+ }
87+
88+ [ Test ]
89+ public void Integration_Performance_ConcurrentAccess ( )
90+ {
91+ // Arrange
92+ var mockProvider = new Mock < IStorageProvider > ( ) ;
93+ var testFeature = new Feature ( new FeatureName ( "ConcurrentTestFeature" ) ,
94+ new Toggle ( Operator . Any , new SimpleCondition { IsEnabled = true } ) ) ;
95+
96+ mockProvider . Setup ( p => p . GetByName ( "ConcurrentTestFeature" ) ) . Returns ( new [ ] { testFeature } ) ;
97+
98+ var featureStore = new FeatureStore ( mockProvider . Object ) ;
99+ var features = new Features ( featureStore ) ;
100+
101+ // Act - Run multiple concurrent evaluations
102+ var tasks = new List < Task < bool > > ( ) ;
103+ var startTime = DateTime . Now ;
104+
105+ for ( int i = 0 ; i < 50 ; i ++ )
106+ {
107+ var task = Task . Run ( ( ) => features . IsEnabled ( "ConcurrentTestFeature" ) ) ;
108+ tasks . Add ( task ) ;
109+ }
110+
111+ Task . WaitAll ( tasks . ToArray ( ) ) ;
112+ var endTime = DateTime . Now ;
113+
114+ // Assert - All should return true, and should complete in reasonable time
115+ Assert . That ( ( endTime - startTime ) . TotalMilliseconds , Is . LessThan ( 5000 ) ) ; // Should complete in under 5 seconds
116+ Assert . That ( tasks . All ( t => t . Result ) , Is . True ) ;
117+ }
118+ }
0 commit comments