33
44using System ;
55using System . Collections . Generic ;
6+ using System . Threading ;
7+ using System . Threading . Tasks ;
68using Microsoft . AspNetCore . Http ;
79using Microsoft . Azure . WebJobs . Rpc . Core . Internal ;
810using Microsoft . Azure . WebJobs . Script . Grpc ;
911using Microsoft . Extensions . DependencyInjection ;
1012using Microsoft . Extensions . FileProviders ;
1113using Microsoft . Extensions . Hosting ;
14+ using Microsoft . Extensions . Logging ;
15+ using Microsoft . Extensions . Logging . Abstractions ;
1216using Microsoft . Extensions . Primitives ;
1317using Moq ;
1418using Xunit ;
@@ -17,6 +21,9 @@ namespace Microsoft.Azure.WebJobs.Script.Tests.Workers.Rpc
1721{
1822 public class ExtensionsCompositeEndpointDataSourceTests
1923 {
24+ private static readonly ILogger < ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware > _logger
25+ = NullLogger < ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware > . Instance ;
26+
2027 [ Fact ]
2128 public void NoActiveHost_NoEndpoints ( )
2229 {
@@ -41,6 +48,7 @@ public void ActiveHostChanged_NullHost_NoEndpoints()
4148 public void ActiveHostChanged_NoExtensions_NoEndpoints ( )
4249 {
4350 Mock < IScriptHostManager > manager = new ( ) ;
51+
4452 ExtensionsCompositeEndpointDataSource dataSource = new ( manager . Object ) ;
4553
4654 IChangeToken token = dataSource . GetChangeToken ( ) ;
@@ -67,6 +75,45 @@ public void ActiveHostChanged_NewExtensions_NewEndpoints()
6775 endpoint => Assert . Equal ( "Test2" , endpoint . DisplayName ) ) ;
6876 }
6977
78+ [ Fact ]
79+ public async Task ActiveHostChanged_MiddlewareWaits_Success ( )
80+ {
81+ Mock < IScriptHostManager > manager = new ( ) ;
82+
83+ ExtensionsCompositeEndpointDataSource dataSource = new ( manager . Object ) ;
84+ ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware middleware =
85+ new ( dataSource , _logger ) { Timeout = Timeout . InfiniteTimeSpan } ;
86+ TestDelegate next = new ( ) ;
87+
88+ Task waiter = middleware . InvokeAsync ( null , next . InvokeAsync ) ;
89+ Assert . False ( waiter . IsCompleted ) ; // should be blocked until we raise the event.
90+
91+ manager . Raise ( x => x . ActiveHostChanged += null , new ActiveHostChangedEventArgs ( null , GetHost ( ) ) ) ;
92+ await waiter . WaitAsync ( TimeSpan . FromSeconds ( 5 ) ) ;
93+ await middleware . Initialized ;
94+ await next . Invoked ;
95+ }
96+
97+ [ Fact ]
98+ public async Task NoActiveHostChanged_MiddlewareWaits_Timeout ( )
99+ {
100+ Mock < IScriptHostManager > manager = new ( ) ;
101+
102+ ExtensionsCompositeEndpointDataSource dataSource = new ( manager . Object ) ;
103+ ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware middleware =
104+ new ( dataSource , _logger ) { Timeout = TimeSpan . Zero } ;
105+ TestDelegate next = new ( ) ;
106+
107+ await middleware . InvokeAsync ( null , next . InvokeAsync ) . WaitAsync ( TimeSpan . FromSeconds ( 5 ) ) ; // should not throw
108+ await Assert . ThrowsAsync < TimeoutException > ( ( ) => middleware . Initialized ) ;
109+ await next . Invoked ;
110+
111+ // invoke again to verify it processes the next request.
112+ next = new ( ) ;
113+ await middleware . InvokeAsync ( null , next . InvokeAsync ) ;
114+ await next . Invoked ;
115+ }
116+
70117 [ Fact ]
71118 public void Dispose_GetThrows ( )
72119 {
@@ -105,5 +152,18 @@ public TestEndpoints(params Endpoint[] endpoints)
105152
106153 public override IChangeToken GetChangeToken ( ) => NullChangeToken . Singleton ;
107154 }
155+
156+ private class TestDelegate
157+ {
158+ private readonly TaskCompletionSource _invoked = new ( ) ;
159+
160+ public Task Invoked => _invoked . Task ;
161+
162+ public Task InvokeAsync ( HttpContext context )
163+ {
164+ _invoked . TrySetResult ( ) ;
165+ return Task . CompletedTask ;
166+ }
167+ }
108168 }
109169}
0 commit comments