@@ -5239,10 +5239,10 @@ await InitializeConnectionAsync(async context =>
52395239
52405240 await context . Response . CompleteAsync ( ) . DefaultTimeout ( ) ;
52415241
5242- Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
5243-
52445242 // Make sure the client gets our results from CompleteAsync instead of from the request delegate exiting.
52455243 await clientTcs . Task . DefaultTimeout ( ) ;
5244+
5245+ Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
52465246 appTcs . SetResult ( ) ;
52475247 }
52485248 catch ( Exception ex )
@@ -5432,6 +5432,7 @@ await WaitForStreamErrorAsync(1, Http2ErrorCode.INTERNAL_ERROR,
54325432 public async Task AbortAfterCompleteAsync_GETWithResponseBodyAndTrailers_ResetsAfterResponse ( )
54335433 {
54345434 var startingTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
5435+ var trailersTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
54355436 var appTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
54365437 var clientTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
54375438 var headers = new [ ]
@@ -5453,6 +5454,9 @@ await InitializeConnectionAsync(async context =>
54535454 context . Response . AppendTrailer ( "CustomName" , "Custom Value" ) ;
54545455
54555456 await context . Response . CompleteAsync ( ) . DefaultTimeout ( ) ;
5457+ // Http2FrameWriter sets Trailers.IsReadOnly to true, but since it's a background task we have to wait for something to indicate it ran
5458+ // That something is the client side receiving the trailers.
5459+ await trailersTcs . Task ;
54565460
54575461 Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
54585462
@@ -5484,6 +5488,7 @@ await InitializeConnectionAsync(async context =>
54845488 withLength : 25 ,
54855489 withFlags : ( byte ) ( Http2HeadersFrameFlags . END_HEADERS | Http2HeadersFrameFlags . END_STREAM ) ,
54865490 withStreamId : 1 ) ;
5491+ trailersTcs . SetResult ( ) ;
54875492 // Stream should return an INTERNAL_ERROR. If there is an unexpected exception from app TCS instead, then throw it here to avoid timeout waiting for the stream error.
54885493 await Task . WhenAny ( WaitForStreamErrorAsync ( 1 , Http2ErrorCode . INTERNAL_ERROR , expectedErrorMessage : null ) , appTcs . Task ) . Unwrap ( ) ;
54895494
@@ -5512,6 +5517,7 @@ await InitializeConnectionAsync(async context =>
55125517 public async Task AbortAfterCompleteAsync_POSTWithResponseBodyAndTrailers_RequestBodyThrows ( )
55135518 {
55145519 var startingTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
5520+ var trailersTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
55155521 var appTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
55165522 var clientTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
55175523 var headers = new [ ]
@@ -5535,7 +5541,10 @@ await InitializeConnectionAsync(async context =>
55355541 context . Response . AppendTrailer ( "CustomName" , "Custom Value" ) ;
55365542
55375543 await context . Response . CompleteAsync ( ) . DefaultTimeout ( ) ;
5538-
5544+ // Http2FrameWriter sets Trailers.IsReadOnly to true, but since it's a background task we have to wait for something to indicate it ran
5545+ // That something is the client side receiving the trailers.
5546+ await trailersTcs . Task ;
5547+
55395548 Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
55405549
55415550 // RequestAborted will no longer fire after CompleteAsync.
@@ -5569,6 +5578,7 @@ await InitializeConnectionAsync(async context =>
55695578 withLength : 25 ,
55705579 withFlags : ( byte ) ( Http2HeadersFrameFlags . END_HEADERS | Http2HeadersFrameFlags . END_STREAM ) ,
55715580 withStreamId : 1 ) ;
5581+ trailersTcs . SetResult ( ) ;
55725582 await WaitForStreamErrorAsync ( 1 , Http2ErrorCode . INTERNAL_ERROR , expectedErrorMessage : null ) ;
55735583
55745584 clientTcs . SetResult ( ) ;
@@ -5596,6 +5606,7 @@ await InitializeConnectionAsync(async context =>
55965606 public async Task ResetAfterCompleteAsync_GETWithResponseBodyAndTrailers_ResetsAfterResponse ( )
55975607 {
55985608 var startingTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
5609+ var trailersTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
55995610 var appTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
56005611 var clientTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
56015612 var headers = new [ ]
@@ -5617,6 +5628,9 @@ await InitializeConnectionAsync(async context =>
56175628 context . Response . AppendTrailer ( "CustomName" , "Custom Value" ) ;
56185629
56195630 await context . Response . CompleteAsync ( ) . DefaultTimeout ( ) ;
5631+ // Http2FrameWriter sets Trailers.IsReadOnly to true, but since it's a background task we have to wait for something to indicate it ran
5632+ // That something is the client side receiving the trailers.
5633+ await trailersTcs . Task ;
56205634
56215635 Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
56225636
@@ -5650,6 +5664,7 @@ await InitializeConnectionAsync(async context =>
56505664 withLength : 25 ,
56515665 withFlags : ( byte ) ( Http2HeadersFrameFlags . END_HEADERS | Http2HeadersFrameFlags . END_STREAM ) ,
56525666 withStreamId : 1 ) ;
5667+ trailersTcs . SetResult ( ) ;
56535668 await WaitForStreamErrorAsync ( 1 , Http2ErrorCode . NO_ERROR , expectedErrorMessage :
56545669 "The HTTP/2 stream was reset by the application with error code NO_ERROR." ) ;
56555670
@@ -5678,6 +5693,7 @@ await WaitForStreamErrorAsync(1, Http2ErrorCode.NO_ERROR, expectedErrorMessage:
56785693 public async Task ResetAfterCompleteAsync_POSTWithResponseBodyAndTrailers_RequestBodyThrows ( )
56795694 {
56805695 var startingTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
5696+ var trailersTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
56815697 var appTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
56825698 var clientTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
56835699 var headers = new [ ]
@@ -5701,6 +5717,9 @@ await InitializeConnectionAsync(async context =>
57015717 context . Response . AppendTrailer ( "CustomName" , "Custom Value" ) ;
57025718
57035719 await context . Response . CompleteAsync ( ) . DefaultTimeout ( ) ;
5720+ // Http2FrameWriter sets Trailers.IsReadOnly to true, but since it's a background task we have to wait for something to indicate it ran
5721+ // That something is the client side receiving the trailers.
5722+ await trailersTcs . Task ;
57045723
57055724 Assert . True ( context . Features . Get < IHttpResponseTrailersFeature > ( ) . Trailers . IsReadOnly ) ;
57065725
@@ -5737,6 +5756,7 @@ await InitializeConnectionAsync(async context =>
57375756 withLength : 25 ,
57385757 withFlags : ( byte ) ( Http2HeadersFrameFlags . END_HEADERS | Http2HeadersFrameFlags . END_STREAM ) ,
57395758 withStreamId : 1 ) ;
5759+ trailersTcs . SetResult ( ) ;
57405760 await WaitForStreamErrorAsync ( 1 , Http2ErrorCode . NO_ERROR , expectedErrorMessage :
57415761 "The HTTP/2 stream was reset by the application with error code NO_ERROR." ) ;
57425762
0 commit comments