/// <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);
        }
示例#2
0
        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);
        }
示例#3
0
        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));
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
 /// <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);
 }