3
3
4
4
using System ;
5
5
using System . Collections . Generic ;
6
+ using System . Threading ;
7
+ using System . Threading . Tasks ;
6
8
using Microsoft . AspNetCore . Http ;
7
9
using Microsoft . Azure . WebJobs . Rpc . Core . Internal ;
8
10
using Microsoft . Azure . WebJobs . Script . Grpc ;
9
11
using Microsoft . Extensions . DependencyInjection ;
10
12
using Microsoft . Extensions . FileProviders ;
11
13
using Microsoft . Extensions . Hosting ;
14
+ using Microsoft . Extensions . Logging ;
15
+ using Microsoft . Extensions . Logging . Abstractions ;
12
16
using Microsoft . Extensions . Primitives ;
13
17
using Moq ;
14
18
using Xunit ;
@@ -17,6 +21,9 @@ namespace Microsoft.Azure.WebJobs.Script.Tests.Workers.Rpc
17
21
{
18
22
public class ExtensionsCompositeEndpointDataSourceTests
19
23
{
24
+ private static readonly ILogger < ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware > _logger
25
+ = NullLogger < ExtensionsCompositeEndpointDataSource . EnsureInitializedMiddleware > . Instance ;
26
+
20
27
[ Fact ]
21
28
public void NoActiveHost_NoEndpoints ( )
22
29
{
@@ -41,6 +48,7 @@ public void ActiveHostChanged_NullHost_NoEndpoints()
41
48
public void ActiveHostChanged_NoExtensions_NoEndpoints ( )
42
49
{
43
50
Mock < IScriptHostManager > manager = new ( ) ;
51
+
44
52
ExtensionsCompositeEndpointDataSource dataSource = new ( manager . Object ) ;
45
53
46
54
IChangeToken token = dataSource . GetChangeToken ( ) ;
@@ -67,6 +75,45 @@ public void ActiveHostChanged_NewExtensions_NewEndpoints()
67
75
endpoint => Assert . Equal ( "Test2" , endpoint . DisplayName ) ) ;
68
76
}
69
77
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
+
70
117
[ Fact ]
71
118
public void Dispose_GetThrows ( )
72
119
{
@@ -105,5 +152,18 @@ public TestEndpoints(params Endpoint[] endpoints)
105
152
106
153
public override IChangeToken GetChangeToken ( ) => NullChangeToken . Singleton ;
107
154
}
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
+ }
108
168
}
109
169
}
0 commit comments