@@ -804,76 +804,6 @@ private static ICacheableKeyRingProvider SetupCreateCacheableKeyRingTestAndCreat
804
804
return CreateKeyRingProvider ( mockKeyManager . Object , mockDefaultKeyResolver . Object , keyManagementOptions ) ;
805
805
}
806
806
807
- [ Theory ]
808
- [ InlineData ( true ) ]
809
- [ InlineData ( false ) ]
810
- [ QuarantinedTest ( "https://github.com/dotnet/aspnetcore/issues/55227" ) ]
811
- public async Task MultipleThreadsForceRefresh ( bool failsToReadKeyRing )
812
- {
813
- const int taskCount = 10 ;
814
- var now = StringToDateTime ( "2015-03-01 00:00:00Z" ) ;
815
-
816
- var expectedKeyRing = new Mock < IKeyRing > ( ) ;
817
- var expectedException = new InvalidOperationException ( nameof ( MultipleThreadsForceRefresh ) ) ;
818
-
819
- var mockCacheableKeyRingProvider = new Mock < ICacheableKeyRingProvider > ( ) ;
820
- mockCacheableKeyRingProvider
821
- . Setup ( o => o . GetCacheableKeyRing ( now ) )
822
- . Returns < DateTimeOffset > ( _ =>
823
- {
824
- // Simulate doing actual work. We need this so that other threads have an opportunity
825
- // to bypass the critical section.
826
- Thread . Sleep ( 200 ) ;
827
-
828
- if ( failsToReadKeyRing )
829
- {
830
- throw expectedException ;
831
- }
832
-
833
- return new CacheableKeyRing (
834
- expirationToken : CancellationToken . None ,
835
- expirationTime : now . AddDays ( 1 ) ,
836
- keyRing : expectedKeyRing . Object ) ;
837
- } ) ;
838
-
839
- var keyRingProvider = CreateKeyRingProvider ( mockCacheableKeyRingProvider . Object ) ;
840
-
841
- var tasks = new Task < IKeyRing > [ taskCount ] ;
842
- for ( var i = 0 ; i < taskCount ; i ++ )
843
- {
844
- tasks [ i ] = Task . Run ( ( ) =>
845
- {
846
- var keyRing = keyRingProvider . GetCurrentKeyRingCore ( now , forceRefresh : true ) ;
847
- return keyRing ;
848
- } ) ;
849
- }
850
-
851
- if ( failsToReadKeyRing )
852
- {
853
- await Task . WhenAll ( tasks ) . ContinueWith ( static _ => { } , TaskScheduler . Default ) ; // Swallow exceptions - we'll inspect individual tasks
854
- Assert . All ( tasks , task => Assert . NotNull ( task . Exception ) ) ;
855
-
856
- // We expect only one task to have thrown expectedException, but it's possible that multiple
857
- // threads made it into the critical section (in sequence, obviously) and each saw expectedException.
858
- // This check is descriptive, rather than normative - it would probably be preferable to have all of
859
- // them see expectedException, but it's presently not propagated to threads that simply wait.
860
- Assert . InRange ( tasks . Count ( task => ReferenceEquals ( expectedException , task . Exception . InnerException ) ) , 1 , taskCount ) ;
861
- }
862
- else
863
- {
864
- var actualKeyRings = await Task . WhenAll ( tasks ) ;
865
- Assert . All ( actualKeyRings , actualKeyRing => ReferenceEquals ( expectedKeyRing , actualKeyRing ) ) ;
866
- }
867
-
868
- // We'd like there to be exactly one call, but it's possible that the first thread will actually
869
- // release the critical section before the last thread attempts to acquire it and the work will
870
- // be redone (by design, since the refresh is forced).
871
- // Even asserting < taskCount is probabilistic - it's possible, though very unlikely, that each
872
- // thread could finish before the next even attempts to enter the criticial section. If this
873
- // proves to be flaky, we could increase taskCount or intentionally slow down GetCacheableKeyRing.
874
- mockCacheableKeyRingProvider . Verify ( o => o . GetCacheableKeyRing ( It . IsAny < DateTimeOffset > ( ) ) , Times . AtMost ( taskCount - 1 ) ) ;
875
- }
876
-
877
807
[ Fact ]
878
808
public async Task MultipleThreadsSeeExpiredCachedValue ( )
879
809
{
0 commit comments