internal static ServerData CreateServer( string pipeName = null, TimeSpan? timeout = null, ICompilerServerHost compilerServerHost = null) { pipeName = pipeName ?? Guid.NewGuid().ToString(); compilerServerHost = compilerServerHost ?? new DesktopCompilerServerHost(DefaultClientDirectory, DefaultSdkDirectory); var taskSource = new TaskCompletionSource<ServerStats>(); var cts = new CancellationTokenSource(); var thread = new Thread(_ => { var listener = new TestableDiagnosticListener(); try { var clientConnectionHost = new NamedPipeClientConnectionHost(compilerServerHost, pipeName); var mutexName = BuildProtocolConstants.GetServerMutexName(pipeName); VBCSCompiler.Run( mutexName, clientConnectionHost, listener, timeout ?? TimeSpan.FromMilliseconds(-1), cts.Token); } finally { var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount); taskSource.SetResult(serverStats); } }); thread.Start(); return new ServerData(cts, taskSource.Task, pipeName); }
public async Task FirstClientCanOverrideDefaultTimeout() { var cts = new CancellationTokenSource(); var listener = new TestableDiagnosticListener(); TimeSpan?newTimeSpan = null; var connectionSource = new TaskCompletionSource <int>(); var diagnosticListener = new Mock <IDiagnosticListener>(); diagnosticListener .Setup(x => x.UpdateKeepAlive(It.IsAny <TimeSpan>())) .Callback <TimeSpan>(ts => { newTimeSpan = ts; }); diagnosticListener .Setup(x => x.ConnectionProcessed(It.IsAny <int>())) .Callback <int>(count => connectionSource.SetResult(count)); var pipeName = Guid.NewGuid().ToString(); var dispatcherTask = Task.Run(() => { var dispatcher = new ServerDispatcher(CreateNopRequestHandler().Object, diagnosticListener.Object); dispatcher.ListenAndDispatchConnections(pipeName, TimeSpan.FromSeconds(1), cancellationToken: cts.Token); }); var seconds = 10; var response = await RunCSharpCompile(pipeName, HelloWorldSourceText, TimeSpan.FromSeconds(seconds)).ConfigureAwait(false); Assert.Equal(BuildResponse.ResponseType.Completed, response.Type); Assert.Equal(1, await connectionSource.Task.ConfigureAwait(false)); Assert.True(newTimeSpan.HasValue); Assert.Equal(seconds, newTimeSpan.Value.TotalSeconds); cts.Cancel(); await dispatcherTask.ConfigureAwait(false); }
public async Task KeepAliveAfterSimultaneousConnection() { var keepAlive = TimeSpan.FromSeconds(1); var listener = new TestableDiagnosticListener(); var pipeName = Guid.NewGuid().ToString(); var dispatcherTask = Task.Run(() => { var dispatcher = new ServerDispatcher(new CompilerRequestHandler(Temp.CreateDirectory().Path), listener); dispatcher.ListenAndDispatchConnections(pipeName, keepAlive); }); var list = new List <Task>(); for (int i = 0; i < 5; i++) { var task = Task.Run(() => RunCSharpCompile(pipeName, HelloWorldSourceText)); list.Add(task); } foreach (var current in list) { await current.ConfigureAwait(false); } await dispatcherTask.ConfigureAwait(false); Assert.Equal(5, listener.ProcessedCount); Assert.True(listener.LastProcessedTime.HasValue); Assert.True((DateTime.Now - listener.LastProcessedTime.Value) > keepAlive); }
internal static async Task <ServerData> CreateServer( string pipeName = null, ICompilerServerHost compilerServerHost = null, bool failingServer = false, string tempPath = null) { // The total pipe path must be < 92 characters on Unix, so trim this down to 10 chars pipeName = pipeName ?? Guid.NewGuid().ToString().Substring(0, 10); compilerServerHost = compilerServerHost ?? BuildServerController.CreateCompilerServerHost(); tempPath = tempPath ?? Path.GetTempPath(); var clientConnectionHost = BuildServerController.CreateClientConnectionHostForServerHost(compilerServerHost, pipeName); if (failingServer) { clientConnectionHost = new FailingClientConnectionHost(clientConnectionHost); } var serverStatsSource = new TaskCompletionSource <ServerStats>(); var serverListenSource = new TaskCompletionSource <bool>(); var cts = new CancellationTokenSource(); var mutexName = BuildServerConnection.GetServerMutexName(pipeName); var listener = new TestableDiagnosticListener(); var task = Task.Run(() => { listener.Listening += (sender, e) => { serverListenSource.TrySetResult(true); }; try { BuildServerController.CreateAndRunServer( pipeName, tempPath, clientConnectionHost, listener, keepAlive: TimeSpan.FromMilliseconds(-1), cancellationToken: cts.Token); } finally { var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount); serverStatsSource.SetResult(serverStats); } }); // The contract of this function is that it will return once the server has started. Spin here until // we can verify the server has started or simply failed to start. while (BuildServerConnection.WasServerMutexOpen(mutexName) != true && !task.IsCompleted) { await Task.Yield(); } if (task.IsFaulted) { throw task.Exception; } return(new ServerData(cts, pipeName, serverStatsSource.Task, serverListenSource.Task, listener.ConnectionCompletedCollection)); }
internal static ServerData CreateServer( string pipeName = null, ICompilerServerHost compilerServerHost = null, bool failingServer = false) { pipeName = pipeName ?? Guid.NewGuid().ToString(); compilerServerHost = compilerServerHost ?? DesktopBuildServerController.CreateCompilerServerHost(); var clientConnectionHost = DesktopBuildServerController.CreateClientConnectionHostForServerHost(compilerServerHost, pipeName); if (failingServer) { clientConnectionHost = new FailingClientConnectionHost(clientConnectionHost); } var serverStatsSource = new TaskCompletionSource <ServerStats>(); var serverListenSource = new TaskCompletionSource <bool>(); var cts = new CancellationTokenSource(); var mutexName = BuildServerConnection.GetServerMutexName(pipeName); var thread = new Thread(_ => { var listener = new TestableDiagnosticListener(); listener.Listening += (sender, e) => { serverListenSource.TrySetResult(true); }; try { DesktopBuildServerController.RunServer( pipeName, clientConnectionHost, listener, keepAlive: TimeSpan.FromMilliseconds(-1), cancellationToken: cts.Token); } finally { var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount); serverStatsSource.SetResult(serverStats); } }); thread.Start(); // The contract of this function is that it will return once the server has started. Spin here until // we can verify the server has started or simply failed to start. while (BuildServerConnection.WasServerMutexOpen(mutexName) != true && thread.IsAlive) { Thread.Yield(); } return(new ServerData(cts, pipeName, serverStatsSource.Task, serverListenSource.Task)); }
internal static async Task <ServerData> CreateServer( string pipeName = null, ICompilerServerHost compilerServerHost = null, IClientConnectionHost clientConnectionHost = null, TimeSpan?keepAlive = null) { // The total pipe path must be < 92 characters on Unix, so trim this down to 10 chars pipeName ??= Guid.NewGuid().ToString().Substring(0, 10); compilerServerHost ??= BuildServerController.CreateCompilerServerHost(); clientConnectionHost ??= BuildServerController.CreateClientConnectionHost(pipeName); keepAlive ??= TimeSpan.FromMilliseconds(-1); var listener = new TestableDiagnosticListener(); var listenerTaskCompletionSource = new TaskCompletionSource <TestableDiagnosticListener>(); var serverListenSource = new TaskCompletionSource <bool>(); var cts = new CancellationTokenSource(); var mutexName = BuildServerConnection.GetServerMutexName(pipeName); var task = Task.Run(() => { try { BuildServerController.CreateAndRunServer( pipeName, compilerServerHost, clientConnectionHost, listener, keepAlive: keepAlive, cancellationToken: cts.Token); } finally { listenerTaskCompletionSource.SetResult(listener); } }); // The contract of this function is that it will return once the server has started. Spin here until // we can verify the server has started or simply failed to start. while (BuildServerConnection.WasServerMutexOpen(mutexName) != true && !task.IsCompleted) { await Task.Yield(); } if (task.IsFaulted) { throw task.Exception; } return(new ServerData(cts, pipeName, listenerTaskCompletionSource.Task)); }
public void KeepAliveAfterSingleConnection() { var connection = CreateClientConnection(CompletionReason.CompilationCompleted); var host = CreateClientConnectionHost( Task.FromResult(connection), new TaskCompletionSource <IClientConnection>().Task); var listener = new TestableDiagnosticListener(); var keepAlive = TimeSpan.FromSeconds(1); var dispatcher = new ServerDispatcher(host, listener); dispatcher.ListenAndDispatchConnections(keepAlive); Assert.Equal(1, listener.CompletedCount); Assert.True(listener.LastProcessedTime.HasValue); Assert.True(listener.HitKeepAliveTimeout); }
public void KeepAliveNoConnections() { var keepAlive = TimeSpan.FromSeconds(3); var connectionHost = new Mock <IClientConnectionHost>(); connectionHost .Setup(x => x.CreateListenTask(It.IsAny <CancellationToken>())) .Returns(new TaskCompletionSource <IClientConnection>().Task); var listener = new TestableDiagnosticListener(); var dispatcher = new ServerDispatcher(connectionHost.Object, listener); var startTime = DateTime.Now; dispatcher.ListenAndDispatchConnections(keepAlive); Assert.True(listener.HitKeepAliveTimeout); }
public async Task KeepAliveAfterSimultaneousConnection() { var totalCount = 2; var readySource = new TaskCompletionSource <bool>(); var list = new List <TaskCompletionSource <ConnectionData> >(); var host = new Mock <IClientConnectionHost>(); host .Setup(x => x.CreateListenTask(It.IsAny <CancellationToken>())) .Returns((CancellationToken ct) => { if (list.Count < totalCount) { var source = new TaskCompletionSource <ConnectionData>(); var client = CreateClientConnection(source.Task); list.Add(source); return(Task.FromResult(client)); } readySource.SetResult(true); return(new TaskCompletionSource <IClientConnection>().Task); }); var keepAlive = TimeSpan.FromSeconds(1); var listener = new TestableDiagnosticListener(); var dispatcherTask = Task.Run(() => { var dispatcher = new ServerDispatcher(host.Object, listener); dispatcher.ListenAndDispatchConnections(keepAlive); }); await readySource.Task.ConfigureAwait(true); foreach (var source in list) { source.SetResult(new ConnectionData(CompletionReason.Completed)); } await dispatcherTask.ConfigureAwait(true); Assert.Equal(totalCount, listener.ProcessedCount); Assert.True(listener.LastProcessedTime.HasValue); Assert.True(listener.HitKeepAliveTimeout); }
public async Task KeepAliveAfterSingleConnection() { var keepAlive = TimeSpan.FromSeconds(1); var listener = new TestableDiagnosticListener(); var pipeName = Guid.NewGuid().ToString(); var dispatcherTask = Task.Run(() => { var dispatcher = new ServerDispatcher(CreateNopRequestHandler().Object, listener); dispatcher.ListenAndDispatchConnections(pipeName, keepAlive); }); await RunCSharpCompile(pipeName, HelloWorldSourceText).ConfigureAwait(false); await dispatcherTask.ConfigureAwait(false); Assert.Equal(1, listener.ProcessedCount); Assert.True(listener.LastProcessedTime.HasValue); Assert.True((DateTime.Now - listener.LastProcessedTime.Value) > keepAlive); }
internal static ServerData CreateServer( string pipeName = null, TimeSpan?timeout = null, ICompilerServerHost compilerServerHost = null, IClientConnectionHost clientConnectionHost = null) { pipeName = pipeName ?? Guid.NewGuid().ToString(); compilerServerHost = compilerServerHost ?? new DesktopCompilerServerHost(DefaultClientDirectory, DefaultSdkDirectory); var serverStatsSource = new TaskCompletionSource <ServerStats>(); var serverListenSource = new TaskCompletionSource <bool>(); var cts = new CancellationTokenSource(); var thread = new Thread(_ => { var listener = new TestableDiagnosticListener(); listener.Listening += (sender, e) => { serverListenSource.TrySetResult(true); }; try { clientConnectionHost = clientConnectionHost ?? new NamedPipeClientConnectionHost(compilerServerHost, pipeName); var mutexName = BuildProtocolConstants.GetServerMutexName(pipeName); VBCSCompiler.Run( mutexName, clientConnectionHost, listener, timeout ?? TimeSpan.FromMilliseconds(-1), cts.Token); } finally { var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount); serverStatsSource.SetResult(serverStats); } }); thread.Start(); return(new ServerData(cts, pipeName, serverStatsSource.Task, serverListenSource.Task)); }
public void KeepAliveAfterMultipleConnection() { var count = 5; var list = new List <Task <IClientConnection> >(); for (var i = 0; i < count; i++) { var connection = CreateClientConnection(CompletionReason.CompilationCompleted); list.Add(Task.FromResult(connection)); } list.Add(new TaskCompletionSource <IClientConnection>().Task); var host = CreateClientConnectionHost(list.ToArray()); var listener = new TestableDiagnosticListener(); var keepAlive = TimeSpan.FromSeconds(1); var dispatcher = new ServerDispatcher(host, listener); dispatcher.ListenAndDispatchConnections(keepAlive); Assert.Equal(count, listener.CompletedCount); Assert.True(listener.LastProcessedTime.HasValue); Assert.True(listener.HitKeepAliveTimeout); }
public void ClientExceptionShouldBeginShutdown() { var client = new Mock <IClientConnection>(); client .Setup(x => x.HandleConnection(It.IsAny <bool>(), It.IsAny <CancellationToken>())) .Throws(new Exception()); var listenCancellationToken = default(CancellationToken); var first = true; var host = new Mock <IClientConnectionHost>(); host .Setup(x => x.CreateListenTask(It.IsAny <CancellationToken>())) .Returns((CancellationToken cancellationToken) => { if (first) { first = false; return(Task.FromResult(client.Object)); } else { listenCancellationToken = cancellationToken; return(Task.Delay(-1, cancellationToken).ContinueWith <IClientConnection>(_ => null, TaskScheduler.Default)); } }); var listener = new TestableDiagnosticListener(); var dispatcher = new ServerDispatcher(host.Object, listener); dispatcher.ListenAndDispatchConnections(TimeSpan.FromSeconds(10)); Assert.True(listener.HasDetectedBadConnection); Assert.True(listenCancellationToken.IsCancellationRequested); }
internal static ServerData CreateServer( string pipeName = null, TimeSpan? timeout = null, ICompilerServerHost compilerServerHost = null, IClientConnectionHost clientConnectionHost = null) { pipeName = pipeName ?? Guid.NewGuid().ToString(); compilerServerHost = compilerServerHost ?? new DesktopCompilerServerHost(DefaultClientDirectory, DefaultSdkDirectory); var serverStatsSource = new TaskCompletionSource<ServerStats>(); var serverListenSource = new TaskCompletionSource<bool>(); var cts = new CancellationTokenSource(); var mutexName = DesktopBuildClient.GetServerMutexName(pipeName); var thread = new Thread(_ => { var listener = new TestableDiagnosticListener(); listener.Listening += (sender, e) => { serverListenSource.TrySetResult(true); }; try { clientConnectionHost = clientConnectionHost ?? new NamedPipeClientConnectionHost(compilerServerHost, pipeName); DesktopBuildServerController.RunServer( pipeName, clientConnectionHost, listener, timeout ?? TimeSpan.FromMilliseconds(-1), cts.Token); } finally { var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount); serverStatsSource.SetResult(serverStats); } }); thread.Start(); // The contract of this function is that it will return once the server has started. Spin here until // we can verify the server has started or simply failed to start. while (DesktopBuildClient.WasServerMutexOpen(mutexName) != true && thread.IsAlive) { Thread.Yield(); } return new ServerData(cts, pipeName, serverStatsSource.Task, serverListenSource.Task); }