@@ -31,9 +31,11 @@ public ReadOnlyCollectionPluginProvider(IReadOnlyCollection<IPlugin> plugins)
3131 public override string HostName => "test.munin-node.localhost" ;
3232
3333 public TestLocalNode (
34+ IAccessRule ? accessRule ,
3435 IReadOnlyList < IPlugin > plugins
3536 )
3637 : base (
38+ accessRule : accessRule ,
3739 logger : null
3840 )
3941 {
@@ -53,10 +55,16 @@ protected override EndPoint GetLocalEndPointToBind()
5355 }
5456
5557 private static NodeBase CreateNode ( )
56- => CreateNode ( plugins : Array . Empty < IPlugin > ( ) ) ;
58+ => CreateNode ( accessRule : null , plugins : Array . Empty < IPlugin > ( ) ) ;
59+
60+ private static NodeBase CreateNode ( IAccessRule ? accessRule )
61+ => CreateNode ( accessRule : accessRule , plugins : Array . Empty < IPlugin > ( ) ) ;
5762
5863 private static NodeBase CreateNode ( IReadOnlyList < IPlugin > plugins )
59- => new TestLocalNode ( plugins ) ;
64+ => CreateNode ( accessRule : null , plugins : plugins ) ;
65+
66+ private static NodeBase CreateNode ( IAccessRule ? accessRule , IReadOnlyList < IPlugin > plugins )
67+ => new TestLocalNode ( accessRule , plugins ) ;
6068
6169 private static TcpClient CreateClient (
6270 IPEndPoint endPoint ,
@@ -79,14 +87,29 @@ out StreamReader reader
7987 private static Task StartSession (
8088 Func < NodeBase , TcpClient , StreamWriter , StreamReader , CancellationToken , Task > action
8189 )
82- => StartSession ( plugins : Array . Empty < IPlugin > ( ) , action : action ) ;
90+ => StartSession (
91+ accessRule : null ,
92+ plugins : Array . Empty < IPlugin > ( ) ,
93+ action : action
94+ ) ;
95+
96+ private static Task StartSession (
97+ IReadOnlyList < IPlugin > plugins ,
98+ Func < NodeBase , TcpClient , StreamWriter , StreamReader , CancellationToken , Task > action
99+ )
100+ => StartSession (
101+ accessRule : null ,
102+ plugins : plugins ,
103+ action : action
104+ ) ;
83105
84106 private static async Task StartSession (
107+ IAccessRule ? accessRule ,
85108 IReadOnlyList < IPlugin > plugins ,
86109 Func < NodeBase , TcpClient , StreamWriter , StreamReader , CancellationToken , Task > action
87110 )
88111 {
89- await using var node = CreateNode ( plugins ) ;
112+ await using var node = CreateNode ( accessRule , plugins ) ;
90113
91114 node . Start ( ) ;
92115
@@ -204,6 +227,66 @@ public async Task AcceptSingleSessionAsync_ClientDisconnected_WhileAwaitingComma
204227 Assert . DoesNotThrowAsync ( async ( ) => await taskAccept ) ;
205228 }
206229
230+ private sealed class AcceptAllAccessRule : IAccessRule {
231+ public bool IsAcceptable ( IPEndPoint remoteEndPoint ) => true ;
232+ }
233+
234+ [ Test ]
235+ public async Task AcceptSingleSessionAsync_IAccessRule_AccessGranted ( )
236+ {
237+ await StartSession (
238+ accessRule : new AcceptAllAccessRule ( ) ,
239+ plugins : Array . Empty < IPlugin > ( ) ,
240+ async static ( node , client , writer , reader , cancellationToken
241+ ) => {
242+ await writer . WriteLineAsync ( "command" , cancellationToken ) ;
243+ await writer . FlushAsync ( cancellationToken ) ;
244+
245+ Assert . That (
246+ await reader . ReadLineAsync ( cancellationToken ) ,
247+ Is . Not . Null ,
248+ "line #1"
249+ ) ;
250+
251+ var connected = ! (
252+ client . Client . Poll ( 1 /*microsecs*/ , SelectMode . SelectRead ) &&
253+ client . Client . Available == 0
254+ ) ;
255+
256+ Assert . That ( connected , Is . True ) ;
257+ } ) ;
258+ }
259+
260+ private sealed class RefuseAllAccessRule : IAccessRule {
261+ public bool IsAcceptable ( IPEndPoint remoteEndPoint ) => false ;
262+ }
263+
264+ [ Test ]
265+ public async Task AcceptSingleSessionAsync_IAccessRule_AccessRefused ( )
266+ {
267+ await StartSession (
268+ accessRule : new RefuseAllAccessRule ( ) ,
269+ plugins : Array . Empty < IPlugin > ( ) ,
270+ async static ( node , client , writer , reader , cancellationToken
271+ ) => {
272+ await writer . WriteLineAsync ( "." , cancellationToken ) ;
273+ await writer . FlushAsync ( cancellationToken ) ;
274+
275+ Assert . That (
276+ await reader . ReadLineAsync ( cancellationToken ) ,
277+ Is . Null ,
278+ "line #1"
279+ ) ;
280+
281+ var connected = ! (
282+ client . Client . Poll ( 1 /*microsecs*/ , SelectMode . SelectRead ) &&
283+ client . Client . Available == 0
284+ ) ;
285+
286+ Assert . That ( connected , Is . False ) ;
287+ } ) ;
288+ }
289+
207290 private class PseudoPluginWithSessionCallback : IPlugin , INodeSessionCallback {
208291 public string Name => throw new NotImplementedException ( ) ;
209292 public PluginGraphAttributes GraphAttributes => throw new NotImplementedException ( ) ;
0 commit comments