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; }