/// <summary> /// Processes user's build request by creating a worker process and forwarding request /// </summary> /// <returns></returns> public async Task ProcessUserBuildRequest(BuildRequestDto buildRequest) { var session = GetSession(buildRequest.SessionId); if (session == null) { session = CreateSession(buildRequest.SessionId); buildRequest.SessionId = session.SessionId; } //set build request so it can be picked up after worker connection session.LastBuildRequest = buildRequest; //reuse existing worker process if still running and connected if (session.WorkerProcess != null && session.WorkerProcess.HasExited == false) { if (session.WorkerClient?.Connected == true) { Logger.LogLine("Recycling worker process for new build request"); listener.SendWorkerMessage(session.WorkerClient, MessageType.ServerBuildRequest, session.LastBuildRequest); return; } else { //worker process has quit or disconnected. Reset references so it can be recreated. Logger.LogLine("Resetting stopped/disconnected worker process for new build request"); ResetSessionWorker(session, WorkerResetReason.WorkerStopped); } } //no worker process, create from scratch so it can connect Logger.LogLine("Creating new worker process for new build request"); await CreateWorkerProcess(session); }
public async void WorkerClient_Builds_On_Request() { //arrange BuildResultDto actualResult = null; //hold actual result var buildRequest = new BuildRequestDto { SessionId = arrangement.SessionId, RunOnSuccess = false, SourceCode = MockSourceCodeRepository.Get_Working_SimpleOutput_Code() }; //act arrangement.WorkerService.StartListening(); arrangement.WorkerService.WorkerConnected += (TcpClient workerClient, string sessionId) => { arrangement.WorkerService.SendWorkerMessage(workerClient, MessageType.ServerBuildRequest, buildRequest); }; arrangement.WorkerService.WorkerCompletedBuild += delegate(TcpClient workerClient, BuildResultDto message) { arrangement.Worker?.Stop(); arrangement.WorkerService?.StopListening(); actualResult = message; }; await arrangement.Worker.Start(arrangement.ServiceHostName, arrangement.ServicePort, arrangement.SessionId); //assert Assert.True(actualResult.IsSuccess); }
public async void WorkerClient_Calls_EntryPoint_With_Correct_Arguments(string source) { //arrange //var arrangement = new WorkerClientArrangement(); //rearrange per theory run (ports!) Queue <ExecutionStateDto> actualStates = new Queue <ExecutionStateDto>(); //hold actual result var buildRequest = new BuildRequestDto { SessionId = arrangement.SessionId, RunOnSuccess = true, SourceCode = source, }; //act arrangement.WorkerService.StartListening(); arrangement.WorkerService.WorkerConnected += (TcpClient workerClient, string sessionId) => { arrangement.WorkerService.SendWorkerMessage(workerClient, MessageType.ServerBuildRequest, buildRequest); }; arrangement.WorkerService.WorkerExecutionStateChanged += delegate(TcpClient workerClient, ExecutionStateDto message) { actualStates.Enqueue(message); if (actualStates.Count >= 2) //if crashed, this will be in the second state { arrangement.Worker?.Stop(); arrangement.WorkerService?.StopListening(); } }; await arrangement.Worker.Start(arrangement.ServiceHostName, arrangement.ServicePort, arrangement.SessionId); //assert Assert.Empty(actualStates.Where(s => s.Exception != null)); Assert.Empty(actualStates.Where(s => s.State == RemoteAppState.Crashed)); }
public async void WorkerClient_Build_Fails_When_Ambiguous_EntryPoint() { //arrange BuildResultDto actualResult = null; //hold actual result var buildRequest = new BuildRequestDto { SessionId = arrangement.SessionId, RunOnSuccess = true, SourceCode = MockSourceCodeRepository.Get_AmbiguousMain_Code() }; //act arrangement.WorkerService.StartListening(); arrangement.WorkerService.WorkerConnected += (TcpClient workerClient, string sessionId) => { arrangement.WorkerService.SendWorkerMessage(workerClient, MessageType.ServerBuildRequest, buildRequest); }; arrangement.WorkerService.WorkerCompletedBuild += delegate(TcpClient workerClient, BuildResultDto message) { arrangement.Worker?.Stop(); arrangement.WorkerService?.StopListening(); actualResult = message; }; await arrangement.Worker.Start(arrangement.ServiceHostName, arrangement.ServicePort, arrangement.SessionId); //assert Assert.False(actualResult.IsSuccess); //CS0017 = Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point. Assert.Equal("CS0017", actualResult.BuildErrors.First().Id); }
public async void WorkerClient_Build_Fails_When_Bad_EntryPoint(string source, string expectedErrorCode) { //arrange BuildResultDto actualResult = null; //hold actual result var buildRequest = new BuildRequestDto { SessionId = arrangement.SessionId, RunOnSuccess = true, SourceCode = source }; //act arrangement.WorkerService.StartListening(); arrangement.WorkerService.WorkerConnected += (TcpClient workerClient, string sessionId) => { arrangement.WorkerService.SendWorkerMessage(workerClient, MessageType.ServerBuildRequest, buildRequest); }; arrangement.WorkerService.WorkerCompletedBuild += delegate(TcpClient workerClient, BuildResultDto message) { arrangement.Worker?.Stop(); arrangement.WorkerService?.StopListening(); actualResult = message; }; await arrangement.Worker.Start(arrangement.ServiceHostName, arrangement.ServicePort, arrangement.SessionId); //assert Assert.False(actualResult.IsSuccess); Assert.Equal(expectedErrorCode, actualResult.BuildErrors.First().Id); }
public async void WorkerClient_Reports_ExecutionState() { //arrange Queue <ExecutionStateDto> actualStates = new Queue <ExecutionStateDto>(); //hold actual result var buildRequest = new BuildRequestDto { SessionId = arrangement.SessionId, RunOnSuccess = true, SourceCode = MockSourceCodeRepository.Get_Working_SimpleOutput_Code() }; //act arrangement.WorkerService.StartListening(); arrangement.WorkerService.WorkerConnected += (TcpClient workerClient, string sessionId) => { arrangement.WorkerService.SendWorkerMessage(workerClient, MessageType.ServerBuildRequest, buildRequest); }; arrangement.WorkerService.WorkerExecutionStateChanged += delegate(TcpClient workerClient, ExecutionStateDto message) { var outputtest = message.Output?.Replace("\r", "[CR]")?.Replace("\n", "LF"); actualStates.Enqueue(message); if (actualStates.Count >= 4) { arrangement.Worker?.Stop(); arrangement.WorkerService?.StopListening(); } }; await arrangement.Worker.Start(arrangement.ServiceHostName, arrangement.ServicePort, arrangement.SessionId); //assert ExecutionStateDto nextState; nextState = actualStates.Dequeue(); Assert.Equal(RemoteAppState.Running, nextState.State); nextState = actualStates.Dequeue(); Assert.Equal(RemoteAppState.WriteOutput, nextState.State); Assert.Equal("All your base are belong to us.", nextState.Output); nextState = actualStates.Dequeue(); Assert.Equal(RemoteAppState.WriteOutput, nextState.State); Assert.Contains("\n", nextState.Output); nextState = actualStates.Dequeue(); Assert.Equal(RemoteAppState.Ended, nextState.State); }
/// <summary> /// Receives build requests from user /// </summary> /// <param name="buildRequest"></param> /// <returns></returns> public async Task Build(BuildRequestDto buildRequest) { buildRequest.SessionId = Context.ConnectionId; await _rcsm.ProcessUserBuildRequest(buildRequest); }