public void ProcessBacktraceForStackFrames() {
            // Arrange
            const int commandId = 3;
            const int fromFrame = 0;
            const int toFrame = 7;
            var resultFactoryMock = new Mock<IEvaluationResultFactory>();
            resultFactoryMock.Setup(factory => factory.Create(It.IsAny<INodeVariable>()))
                .Returns(() => new NodeEvaluationResult(0, null, null, null, null, null, NodeExpressionType.None, null));
            var backtraceCommand = new BacktraceCommand(commandId, resultFactoryMock.Object, fromFrame, toFrame);
            JObject backtraceMessage = SerializationTestData.GetBacktraceResponse();

            // Act
            backtraceCommand.ProcessResponse(backtraceMessage);

            // Assert
            Assert.AreEqual(7, backtraceCommand.StackFrames.Count);
            NodeStackFrame firstFrame = backtraceCommand.StackFrames[0];
            Assert.AreEqual(NodeVariableType.AnonymousFunction, firstFrame.FunctionName);
            Assert.AreEqual(@"C:\Users\Tester\documents\visual studio 2012\Projects\NodejsApp1\NodejsApp1\server.js", firstFrame.FileName);
            Assert.AreEqual(22, firstFrame.Line);
            Assert.AreEqual(0, firstFrame.Column);
            Assert.AreEqual(15, firstFrame.Locals.Count);
            Assert.AreEqual(5, firstFrame.Parameters.Count);
            Assert.IsNotNull(backtraceCommand.Modules);
            Assert.AreEqual(3, backtraceCommand.Modules.Count);
            resultFactoryMock.Verify(factory => factory.Create(It.IsAny<INodeVariable>()), Times.Exactly(51));
        }
        public void CreateBacktraceCommand() {
            // Arrange
            const int commandId = 3;
            const int fromFrame = 0;
            const int toFrame = 7;
            var resultFactoryMock = new Mock<IEvaluationResultFactory>();

            // Act
            var backtraceCommand = new BacktraceCommand(commandId, resultFactoryMock.Object, fromFrame, toFrame);

            // Assert
            Assert.AreEqual(commandId, backtraceCommand.Id);
            Assert.AreEqual(
                string.Format(
                    "{{\"command\":\"backtrace\",\"seq\":{0},\"type\":\"request\",\"arguments\":{{\"fromFrame\":{1},\"toFrame\":{2},\"inlineRefs\":true}}}}",
                    commandId, fromFrame, toFrame),
                backtraceCommand.ToString());
        }
        public void ProcessBacktraceForCallstackDepth() {
            // Arrange
            const int commandId = 3;
            const int fromFrame = 0;
            const int toFrame = 7;
            var resultFactoryMock = new Mock<IEvaluationResultFactory>();
            resultFactoryMock.Setup(factory => factory.Create(It.IsAny<INodeVariable>()))
                .Returns(() => new NodeEvaluationResult(0, null, null, null, null, null, NodeExpressionType.None, null));
            var backtraceCommand = new BacktraceCommand(commandId, resultFactoryMock.Object, fromFrame, toFrame, true);
            JObject backtraceMessage = SerializationTestData.GetBacktraceResponse();

            // Act
            backtraceCommand.ProcessResponse(backtraceMessage);

            // Assert
            Assert.AreEqual(7, backtraceCommand.CallstackDepth);
            Assert.IsNotNull(backtraceCommand.Modules);
            Assert.AreEqual(0, backtraceCommand.Modules.Count);
            Assert.IsNotNull(backtraceCommand.StackFrames);
            Assert.AreEqual(0, backtraceCommand.StackFrames.Count);
            resultFactoryMock.Verify(factory => factory.Create(It.IsAny<INodeVariable>()), Times.Never);
        }
        /// <summary>
        /// Retrieves a backtrace for current execution point.
        /// </summary>
        /// <returns>Whether program execution in progress.</returns>
        private async Task<bool> PerformBacktraceAsync(CancellationToken cancellationToken = new CancellationToken()) {
            // CONSIDER:  Lazy population of callstacks
            // Given the VS Debugger UI always asks for full callstacks, we always ask Node.js for full backtraces.
            // Given the nature or Node.js code, deep callstacks are expected to be rare.
            // Although according to the V8 docs (http://code.google.com/p/v8/wiki/DebuggerProtocol) the 'backtrace'
            // request takes a 'bottom' parameter, empirically, Node.js fails requests with it set.  Here we
            // approximate 'bottom' for 'toFrame' using int.MaxValue.  Node.js silently handles toFrame depths
            // greater than the current callstack.
            var backtraceCommand = new BacktraceCommand(CommandId, _resultFactory, 0, int.MaxValue);
            if (!await TrySendRequestAsync(backtraceCommand, cancellationToken).ConfigureAwait(false)) {
                return false;
            }

            // Add extracted modules
            AddModules(backtraceCommand.Modules.Values);

            // Add stack frames
            List<NodeStackFrame> stackFrames = GetLocalFrames(backtraceCommand.StackFrames).ToList();

            // Collects results of number type which have null values and perform a lookup for actual values
            var numbersWithNullValue = new List<NodeEvaluationResult>();
            foreach (NodeStackFrame stackFrame in stackFrames) {
                numbersWithNullValue.AddRange(stackFrame.Locals.Concat(stackFrame.Parameters)
                    .Where(p => p.TypeName == NodeVariableType.Number && p.StringValue == null));
            }

            if (numbersWithNullValue.Count > 0) {
                var lookupCommand = new LookupCommand(CommandId, _resultFactory, numbersWithNullValue);
                if (await TrySendRequestAsync(lookupCommand, cancellationToken).ConfigureAwait(false)) {
                    foreach (NodeEvaluationResult targetResult in numbersWithNullValue) {
                        NodeEvaluationResult lookupResult = lookupCommand.Results[targetResult.Handle][0];
                        targetResult.StringValue = targetResult.HexValue = lookupResult.StringValue;
                    }
                }
            }

            MainThread.Frames = stackFrames;

            return backtraceCommand.Running;
        }
 private async Task<int> GetCallstackDepthAsync(CancellationToken cancellationToken = new CancellationToken()) {
     var backtraceCommand = new BacktraceCommand(CommandId, _resultFactory, 0, 1, true);
     await TrySendRequestAsync(backtraceCommand, cancellationToken).ConfigureAwait(false);
     return backtraceCommand.CallstackDepth;
 }
 internal bool IsRunning() {
     var backtraceCommand = new BacktraceCommand(CommandId, _resultFactory, fromFrame: 0, toFrame: 1);
     var tokenSource = new CancellationTokenSource(_timeout);
     var task = TrySendRequestAsync(backtraceCommand, tokenSource.Token);
     if (task.Wait(_timeout) && task.Result) {
         return backtraceCommand.Running;
     }
     return false;
 }
 internal bool IsRunning() {
     var backtraceCommand = new BacktraceCommand(CommandId, _resultFactory, 0, 1);
     if (TrySendRequestAsync(backtraceCommand).GetAwaiter().GetResult()) {
         return backtraceCommand.Running;
     }
     return false;
 }