Пример #1
0
        private string GetMessage(Stream stdout, int timeout, Process debugAdapter, DebugAdapterRunner runner)
        {
            // Read header of message
            byte[] header = ReadBlockFromStream(stdout, debugAdapter, DAPConstants.ContentLength.Length, timeout);
            VerifyValueOfBuffer(header, DAPConstants.ContentLength);

            // Read the length (in bytes) of the json message
            int messageLengthBytes = 0;
            int nextByte           = -1;

            while (true)
            {
                nextByte = stdout.ReadByte();
                if (nextByte >= '0' && nextByte <= '9')
                {
                    messageLengthBytes = messageLengthBytes * 10 + nextByte - '0';
                }
                else
                {
                    break;
                }
            }

            // Read and verify TWO_CRLF
            byte[] twoCRLF = new byte[DAPConstants.TwoCrLf.Length];
            twoCRLF[0] = (byte)nextByte;

            // Read one less byte because we have the first byte and copy into twoCRLF byte array
            byte[] oneMinustwoCRLF = ReadBlockFromStream(stdout, debugAdapter, DAPConstants.TwoCrLf.Length - 1, timeout);
            Array.Copy(oneMinustwoCRLF, 0, twoCRLF, 1, oneMinustwoCRLF.Length);

            VerifyValueOfBuffer(twoCRLF, DAPConstants.TwoCrLf);

            // Read the message contents
            byte[] messageBuffer = ReadBlockFromStream(stdout, debugAdapter, messageLengthBytes, timeout);

            return(Encoding.UTF8.GetString(messageBuffer, 0, messageLengthBytes));
        }
Пример #2
0
 public virtual void Run(DebugAdapterRunner runner)
 {
 }
Пример #3
0
        /// <summary>
        /// Runs a command against the debugger.
        /// </summary>
        /// <param name="command">The command to run.</param>
        /// <param name="expectedEvents">[OPTIONAL] If the command causes an event to occur, pass the expected event(s)</param>
        private void Run(DarRunner darRunner, ILoggingComponent log, params IEvent[] expectedEvents)
        {
            Parameter.ThrowIfNull(darRunner, nameof(darRunner));

            log?.WriteLine("Running command {0}", this.ToString());
            log?.WriteLine("Command '{0}' expecting response: {1}", this.Name, this.ExpectedResponse.ToString());

            DebugAdapterResponse darCommandResponse = GetDarResponse(this.ExpectedResponse);
            DebugAdapterCommand  darCommand         = new DebugAdapterCommand(
                this.Name,
                this.Args,
                new[] { darCommandResponse });
            List <Tuple <DebugAdapterResponse, IEvent> > darEventMap = new List <Tuple <DebugAdapterResponse, IEvent> >(expectedEvents.Length);

            // Add additional expected events to match if requested
            if (expectedEvents != null && expectedEvents.Length > 0)
            {
                if (expectedEvents.Length > 1)
                {
                    log?.WriteLine("Command '{0}' expecting {1} events:", this.Name, expectedEvents.Length);
                }

                foreach (var expectedEvent in expectedEvents)
                {
                    DebugAdapterResponse darEventResponse = GetDarResponse(expectedEvent);
                    darCommand.ExpectedResponses.Add(darEventResponse);
                    darEventMap.Add(Tuple.Create(darEventResponse, expectedEvent));

                    // Debug info for expected response
                    string eventMessage = expectedEvents.Length > 1 ? "  - {1}" : "Command '{0}' expecting event: {1}";
                    log?.WriteLine(eventMessage, this.Name, expectedEvent.ToString());
                }
            }

            // Allow the command to override the timeout
            int overrideTimeout = Convert.ToInt32(this.Timeout.TotalMilliseconds);
            int savedTimeout    = darRunner.ResponseTimeout;

            try
            {
                if (overrideTimeout > 0)
                {
                    darRunner.ResponseTimeout = overrideTimeout;
                    log?.WriteLine("Command '{0}' timeout set to {1:n0} seconds.", this.Name, this.Timeout.TotalSeconds);
                }

                darCommand.Run(darRunner);

                // Allow the command to retrieve properties from the actual matched response.
                string responseJson = JsonConvert.SerializeObject(darCommandResponse.Match);
                if (!string.IsNullOrWhiteSpace(responseJson))
                {
                    this.ProcessActualResponse(new ActualResponse(responseJson));
                }

                // Allow the events to retrieve properties from the actual event.
                foreach (var darEvent in darEventMap)
                {
                    string eventJson = JsonConvert.SerializeObject(darEvent.Item1.Match);
                    darEvent.Item2.ProcessActualResponse(new ActualResponse(eventJson));
                }
            }
            catch (Exception ex)
            {
                // Add information to the log when the exception occurs
                log?.WriteLine("ERROR: Running command '{0}'. Exception thrown.", this.Name);
                log?.WriteLine(UDebug.ExceptionToString(ex));

                // The DARException is not serializable, create a new exception
                if (ex is DARException)
                {
                    throw new RunnerException(ex.Message);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (overrideTimeout > 0)
                {
                    darRunner.ResponseTimeout = savedTimeout;
                }
            }
        }
Пример #4
0
 public override void Run(DarRunner darRunner)
 {
     this.Run(darRunner, null);
 }
Пример #5
0
        private string CreateDispatcherRequest(DebugAdapterRunner runner)
        {
            DispatcherRequest request = new DispatcherRequest(runner.GetNextSequenceNumber(), this.Name, this.args);

            return(runner.SerializeMessage(request));
        }
Пример #6
0
        public override void Run(DebugAdapterRunner runner)
        {
            // Send the request
            string request = CreateDispatcherRequest(runner);

            // VSCode doesn't send /n at the end. If this is writeline, then concord hangs
            runner.DebugAdapter.StandardInput.Write(request);

            // Process + validate responses
            List <object> responseList = new List <object>();
            int           currentExpectedResponseIndex = 0;

            // Loop until we have received as many expected responses as expected
            while (currentExpectedResponseIndex < this.ExpectedResponses.Count)
            {
                string    receivedMessage      = null;
                Exception getMessageExeception = null;
                try
                {
                    receivedMessage = this.GetMessage(
                        runner.DebugAdapter.StandardOutput.BaseStream,
                        runner.ResponseTimeout,
                        runner.DebugAdapter,
                        runner);
                }
                catch (Exception e)
                {
                    getMessageExeception = e;
                }

                if (getMessageExeception != null)
                {
                    if (!runner.DebugAdapter.HasExited)
                    {
                        // If it hasn't exited yet, wait a little bit longer to make sure it isn't just about to exit
                        try
                        {
                            runner.DebugAdapter.WaitForExit(500);
                        }
                        catch
                        { }
                    }

                    string messageStart;
                    if (runner.DebugAdapter.HasExited)
                    {
                        if (runner.HasAsserted())
                        {
                            messageStart = string.Format(CultureInfo.CurrentCulture, "The debugger process has asserted and exited with code '{0}' without sending all expected responses. See test log for assert details.", runner.DebugAdapter.ExitCode);
                        }
                        else
                        {
                            messageStart = string.Format(CultureInfo.CurrentCulture, "The debugger process has exited with code '{0}' without sending all expected responses.", runner.DebugAdapter.ExitCode);
                        }
                    }
                    else if (getMessageExeception is TimeoutException)
                    {
                        if (runner.HasAsserted())
                        {
                            messageStart = "The debugger process has asserted. See test log for assert details.";
                        }
                        else
                        {
                            messageStart = "Expected response not found before timeout.";
                        }
                    }
                    else
                    {
                        messageStart = "Exception while reading message from debug adpter. " + getMessageExeception.Message;
                    }

                    string expectedResponseText = JsonConvert.SerializeObject(this.ExpectedResponses[currentExpectedResponseIndex].Response);
                    string actualResponseText   = string.Empty;

                    for (int i = 0; i < responseList.Count; i++)
                    {
                        actualResponseText += string.Format(CultureInfo.CurrentCulture, "{0}. {1}\n", (i + 1), JsonConvert.SerializeObject(responseList[i]));
                    }

                    string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0}\nExpected = {1}\nActual Responses =\n{2}",
                                                        messageStart, expectedResponseText, actualResponseText);

                    throw new DARException(errorMessage);
                }

                try
                {
                    DispatcherMessage dispatcherMessage = JsonConvert.DeserializeObject <DispatcherMessage>(receivedMessage);

                    if (dispatcherMessage.type == "event")
                    {
                        DispatcherEvent dispatcherEvent = JsonConvert.DeserializeObject <DispatcherEvent>(receivedMessage);
                        responseList.Add(dispatcherEvent);

                        if (dispatcherEvent.eventType == "stopped")
                        {
                            runner.CurrentThreadId = dispatcherEvent.body.threadId;
                        }

                        var expected = this.ExpectedResponses[currentExpectedResponseIndex];
                        if (Utils.CompareObjects(expected.Response, dispatcherEvent, expected.IgnoreOrder))
                        {
                            expected.Match = dispatcherEvent;
                            currentExpectedResponseIndex++;
                        }
                    }
                    else if (dispatcherMessage.type == "response")
                    {
                        DispatcherResponse dispatcherResponse = JsonConvert.DeserializeObject <DispatcherResponse>(receivedMessage);
                        responseList.Add(dispatcherResponse);

                        var expected = this.ExpectedResponses[currentExpectedResponseIndex];
                        if (Utils.CompareObjects(expected.Response, dispatcherResponse, expected.IgnoreOrder))
                        {
                            expected.Match = dispatcherResponse;
                            currentExpectedResponseIndex++;
                        }
                    }
                    else if (dispatcherMessage.type == "request")
                    {
                        runner.HandleCallbackRequest(receivedMessage);
                    }
                    else
                    {
                        throw new DARException(String.Format(CultureInfo.CurrentCulture, "Unknown Dispatcher Message type: '{0}'", dispatcherMessage.type));
                    }
                }
                catch (JsonReaderException)
                {
                    runner.AppendLineToDebugAdapterOutput("Response could not be parsed as json. This was the response:");
                    runner.AppendLineToDebugAdapterOutput(receivedMessage);
                    throw;
                }
            }
        }