public void TestOptimizedBpsAndSource(ITestSettings settings) { this.TestPurpose("Tests basic operation of bps and source information for optimized app"); this.WriteSettings(settings); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, Name, DebuggeeMonikers.Optimization.OptimizationWithSymbols); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); SourceBreakpoints mainBreakpoints = debuggee.Breakpoints(SourceName, 68); SourceBreakpoints userDefinedClassBreakpoints = debuggee.Breakpoints(UserDefinedClassName, 8, 15, 54); this.Comment("Set initial breakpoints"); runner.SetBreakpoints(mainBreakpoints); runner.SetBreakpoints(userDefinedClassBreakpoints); this.Comment("Launch and run until 1st bp"); runner.Expects.HitBreakpointEvent(UserDefinedClassName, 8) .AfterConfigurationDone(); this.Comment("run until 2nd bp"); runner.Expects.HitBreakpointEvent(UserDefinedClassName, 54) .AfterContinue(); this.Comment("run until 3rd bp"); runner.Expects.HitBreakpointEvent(SourceName, 68) .AfterContinue(); //Todo: this has different behavior on Mac(:16), Other Platforms(15) I have logged bug#247891 to track this.Comment("run until 4th bp"); runner.ExpectBreakpointAndStepToTarget(UserDefinedClassName, 15, 16).AfterContinue(); this.Comment("continue to next bp"); runner.Expects.HitBreakpointEvent(UserDefinedClassName, 54) .AfterContinue(); this.Comment("Check the current callstack frame"); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Get current frame object"); IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify current frame"); threadInspector.AssertStackFrameNames(true, "Foo::Sum"); } this.Comment("step out to main entry"); runner.Expects.HitStepEvent(SourceName, 69) .AfterStepOut(); runner.Expects.ExitedEvent(0).TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void EvaluateInvalidExpression(ITestSettings settings) { this.TestPurpose("To test invalid expression evaluation return apropriate errors."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a breakpoint so that we can stop at a line."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 31)); this.Comment("To start debugging and hit breakpoint."); runner.Expects.HitBreakpointEvent().AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("To evaluate some invalid expression on curren stack frame."); currentFrame.AssertEvaluateAsError("notExistVar", EvaluateContext.Watch); } this.Comment("Continue to run to exist."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void CallStackBasic(ITestSettings settings) { this.TestPurpose("To check all frames of callstack on a thead and evaluation on each frame."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); this.Comment("Here are stack frames in a list we expect the actual to match with this."); StackFrame[] expectedstackFrames = ExpressionTests.GenerateFramesList(settings.DebuggerSettings); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a breakpoint so that we can stop after starting debugging."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 19)); this.Comment("To start debugging and break"); runner.Expects.StoppedEvent(StoppedReason.Breakpoint, SinkHelper.Expression, 19).AfterConfigurationDone(); this.Comment("To step in several times into the innermost layer of a recursive call."); runner.ExpectStepAndStepToTarget(SinkHelper.Expression, 9, 10).AfterStepIn(); runner.Expects.HitStepEvent(SinkHelper.Expression, 12).AfterStepIn(); runner.ExpectStepAndStepToTarget(SinkHelper.Expression, 9, 10).AfterStepIn(); runner.Expects.HitStepEvent(SinkHelper.Expression, 12).AfterStepIn(); runner.ExpectStepAndStepToTarget(SinkHelper.Expression, 9, 10).AfterStepIn(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IEnumerable <IFrameInspector> stackOfCurrentThread = threadInspector.Stack; this.Comment("To verify the count of stack frames count."); Assert.True(stackOfCurrentThread.Count() >= 13, "Expected the stack frame count to be at least 13 deep"); this.Comment("To verify each frame, include frame name, line number and source name."); int index = 0; foreach (IFrameInspector frame in stackOfCurrentThread) { if (index >= 13) { break; } StackFrame expectedstackFrame = expectedstackFrames[index]; this.Comment("Comparing Names. Expecected: {0}, Actual: {1}", expectedstackFrame.Name, frame.Name); Assert.Contains(expectedstackFrame.Name, frame.Name, StringComparison.Ordinal); this.Comment("Comparing line number. Expecected: {0}, Actual: {1}", expectedstackFrame.Line, frame.Line); Assert.Equal(expectedstackFrame.Line, frame.Line); this.Comment("Comparing Source Name. Expecected: {0}, Actual: {1}", expectedstackFrame.SourceName, frame.SourceName); Assert.Equal(expectedstackFrame.SourceName, frame.SourceName); index++; } } this.Comment("Continue to run to exist."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void RunModeBreakpoints(ITestSettings settings) { this.TestPurpose("Tests setting breakpoints while in run mode"); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Breakpoint); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fNonTerminating"); runner.ConfigurationDone(); // Wait a second to ensure the debuggee has entered run mode, then try to set a breakpoint Thread.Sleep(TimeSpan.FromSeconds(1)); this.Comment("Set a function breakpoint while in run mode"); FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("NonTerminating::DoSleep"); runner.ExpectBreakpointAndStepToTarget(SinkHelper.NonTerminating, startLine: 37, targetLine: 38) .AfterSetFunctionBreakpoints(functionBreakpoints); this.Comment("Remove function breakpoint"); functionBreakpoints.Remove("NonTerminating::DoSleep"); runner.SetFunctionBreakpoints(functionBreakpoints); this.Comment("Continue, set a line breakpoint while in run mode"); runner.Continue(); // Wait a second to ensure the debuggee has entered run mode, then try to set a breakpoint Thread.Sleep(TimeSpan.FromSeconds(1)); runner.Expects.HitBreakpointEvent(SinkHelper.NonTerminating, 28) .AfterSetBreakpoints(debuggee.Breakpoints(SinkHelper.NonTerminating, 28)); this.Comment("Escape loop"); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector firstFrame = threadInspector.Stack.First(); this.WriteLine(firstFrame.ToString()); firstFrame.GetVariable("this", "shouldExit").Value = "1"; } this.Comment("Continue until end"); runner.Expects.ExitedEvent() .TerminatedEvent() .AfterContinue(); runner.DisconnectAndVerify(); } }
public void ExecutionStepBasic(ITestSettings settings) { this.TestPurpose("Verify basic step in/over/out should work during debugging"); this.WriteSettings(settings); this.Comment("Open the kitchen sink debuggee for execution tests."); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Execution); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fCalling"); this.Comment("Set initial source breakpoints"); SourceBreakpoints bps = debuggee.Breakpoints(SinkHelper.Main, 21, 33); runner.SetBreakpoints(bps); this.Comment("Launch and run until hit the first entry"); runner.Expects.HitBreakpointEvent(SinkHelper.Main, 21).AfterConfigurationDone(); this.Comment("Step over the function"); runner.Expects.HitStepEvent(SinkHelper.Main, 23).AfterStepOver(); this.Comment("Continue to hit the second entry"); runner.Expects.HitBreakpointEvent(SinkHelper.Main, 33).AfterContinue(); this.Comment("Step in the function"); runner.ExpectStepAndStepToTarget(SinkHelper.Feature, startLine: 19, targetLine: 20).AfterStepIn(); this.Comment("Step over the function"); runner.Expects.HitStepEvent(SinkHelper.Feature, 21).AfterStepOver(); runner.Expects.HitStepEvent(SinkHelper.Feature, 22).AfterStepOver(); this.Comment("Step in the function"); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, startLine: 47, targetLine: 48).AfterStepIn(); this.Comment("Step out the function"); runner.ExpectStepAndStepToTarget(SinkHelper.Feature, startLine: 22, targetLine: 23).AfterStepOut(); this.Comment("Continue running at the end of application"); runner.Expects.ExitedEvent() .TerminatedEvent() .AfterContinue(); this.Comment("Verify debugger and debuggee closed"); runner.DisconnectAndVerify(); } }
public void TestSharedLibWithoutSymbol(ITestSettings settings) { this.TestPurpose("Tests basic bps and source information for shared library without symbols"); this.WriteSettings(settings); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, Name, DebuggeeMonikers.Optimization.OptimizationWithoutSymbols); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); SourceBreakpoints mainBreakpoints = debuggee.Breakpoints(SourceName, 87, 91); this.Comment("Set initial breakpoints"); runner.SetBreakpoints(mainBreakpoints); this.Comment("Launch and run until 1st bp"); runner.Expects.HitBreakpointEvent(SourceName, 87) .AfterConfigurationDone(); this.Comment("Step into the library source"); runner.Expects.HitStepEvent(SourceName, 89) .AfterStepIn(); this.Comment("Check the stack for debugging shared library without symbols"); using (IThreadInspector inspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = inspector.Stack.First(); inspector.AssertStackFrameNames(true, "main"); this.Comment("run to continue to 2nd bp"); runner.Expects.HitBreakpointEvent(SourceName, 91) .AfterContinue(); this.Comment("Check the stack for debugging shared library without symbols"); currentFrame = inspector.Stack.First(); inspector.AssertStackFrameNames(true, "main"); this.Comment("Check the local variables in main function"); IVariableInspector age = currentFrame.Variables["age"]; Assert.Matches("31", age.Value); } runner.DisconnectAndVerify(); } }
public void AttachAsyncBreak(ITestSettings settings) { this.TestPurpose("Verifies attach and that breakpoints can be set from break mode."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Attach); Process debuggeeProcess = debuggee.Launch("-fNonTerminating", "-fCalling"); using (ProcessHelper.ProcessCleanup(this, debuggeeProcess)) using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Attach to debuggee"); runner.Attach(settings.DebuggerSettings, debuggeeProcess); runner.ConfigurationDone(); this.Comment("Attempt to break all"); StoppedEvent breakAllEvent = new StoppedEvent(StoppedReason.Pause); runner.Expects.Event(breakAllEvent) .AfterAsyncBreak(); this.WriteLine("Break all stopped on:"); this.WriteLine(breakAllEvent.ActualEvent.ToString()); this.Comment("Set breakpoint while breaking code."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.NonTerminating, 28)); this.Comment("Start running after the async break (since we have no idea where we are) and then hit the breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.NonTerminating, 28) .AfterContinue(); this.Comment("Evaluate the shouldExit member to true to stop the infinite loop."); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector firstFrame = threadInspector.Stack.First(); this.WriteLine(firstFrame.ToString()); firstFrame.GetVariable("shouldExitLocal").Value = "true"; } this.Comment("Continue until debuggee exists"); runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue(); this.Comment("Verify debugger and debuggee closed"); runner.DisconnectAndVerify(); Assert.True(debuggeeProcess.HasExited, "Debuggee still running."); } }
private void TestEnvironmentVariable(ITestSettings settings, string variableName, string variableValue, bool newTerminal) { this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Environment); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, false, "-fEnvironment") { StopAtEntry = false }; if (variableValue != null) { launch.Args.environment = new EnvironmentEntry[] { new EnvironmentEntry { Name = variableName, Value = variableValue } }; } launch.Args.externalConsole = newTerminal; runner.RunCommand(launch); this.Comment("Set breakpoint"); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Environment, 14)); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify locals variables on current frame."); currentFrame.AssertEvaluateAsString("varValue1", EvaluateContext.Watch, variableValue); } this.Comment("Continue until end"); runner.Expects.ExitedEvent() .TerminatedEvent() .AfterContinue(); runner.DisconnectAndVerify(); } }
public void ThreadingBreakpoint(ITestSettings settings) { this.TestPurpose("Test breakpoint on multiple threads."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Threading); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Launching debuggee. Set breakpoint in worker thread code."); runner.Launch(settings.DebuggerSettings, true, debuggee, "-fThreading"); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Threading, 16)); // Turned on stop at entry, so should stop before anything is executed. // On Concord, this is a reason of "entry" versus "step" when it is hit. if (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg) { runner.Expects.HitEntryEvent().AfterConfigurationDone(); } else { runner.Expects.HitStepEvent() .AfterConfigurationDone(); } // Since there are 4 worker threads, expect to hit the // breakpoint 4 times, once on each thread. for (int i = 1; i <= 4; i++) { StoppedEvent breakpointEvent = new StoppedEvent(StoppedReason.Breakpoint, SinkHelper.Threading, 16); this.Comment("Run until breakpoint #{0}.", i); runner.Expects.Event(breakpointEvent).AfterContinue(); this.WriteLine("Stopped on thread: {0}", breakpointEvent.ThreadId); this.WriteLine("Ensure stopped thread exists in ThreadList"); IEnumerable <IThreadInfo> threadInfo = runner.GetThreads(); Assert.True(threadInfo.Any(thread => thread.Id == breakpointEvent.ThreadId), string.Format(CultureInfo.CurrentCulture, "ThreadId {0} should exist in ThreadList", breakpointEvent.ThreadId)); } this.Comment("Run to end."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void TestOptimizedLocals(ITestSettings settings) { this.TestPurpose("Tests basic local expression which is not been optimized"); this.WriteSettings(settings); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, Name, DebuggeeMonikers.Optimization.OptimizationWithSymbols); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); SourceBreakpoints userDefinedClassBreakpoints = debuggee.Breakpoints(UserDefinedClassName, 54); this.Comment("Set initial breakpoints"); runner.SetBreakpoints(userDefinedClassBreakpoints); this.Comment("Launch and run until 1st bp"); runner.Expects.HitBreakpointEvent(UserDefinedClassName, 54) .AfterConfigurationDone(); this.Comment("Check the un-optimized values"); using (IThreadInspector inspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = inspector.Stack.First(); IVariableInspector sum = currentFrame.Variables["sum"]; IVariableInspector first = currentFrame.Variables["first"]; this.Comment("Check the local variables in sub function"); Assert.Matches("^0", sum.Value); Assert.Matches("^1", first.Value); this.Comment("Step out"); runner.Expects.HitStepEvent(SourceName, 66) .AfterStepOut(); this.Comment("Evaluate the expression:"); currentFrame = inspector.Stack.First(); inspector.AssertStackFrameNames(true, "main"); } runner.DisconnectAndVerify(); } }
public void LocalsBasic(ITestSettings settings) { this.TestPurpose("Check primitives displying in locals."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a line breakpoints so that we can stop."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 31)); this.Comment("To start debugging and break"); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("To verify locals variables on current frame."); Assert.Subset(new HashSet <string>() { "mybool", "mychar", "myint", "mywchar", "myfloat", "mydouble", "this" }, currentFrame.Variables.ToKeySet()); currentFrame.AssertVariables( "mybool", "true", "myint", "100"); currentFrame.GetVariable("mychar").AssertValueAsChar('A'); currentFrame.GetVariable("mywchar").AssertValueAsWChar('z'); currentFrame.GetVariable("myfloat").AssertValueAsFloat(299); currentFrame.GetVariable("mydouble").AssertValueAsDouble(321); } this.Comment("Run to completion"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void BreakpointBinding(ITestSettings settings) { this.TestPurpose("Tests that breakpoints are bound to the correct locations"); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Breakpoint); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); SourceBreakpoints callingBreakpoints = debuggee.Breakpoints(SinkHelper.Calling, 11); FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("Calling::CoreRun"); // VsDbg does not fire Breakpoint Change events when breakpoints are set. // Instead it sends a new breakpoint event when it is bound (after configuration done). bool bindsLate = (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg); this.Comment("Set a breakpoint at a location that has no executable code, expect it to be moved to the next line"); runner.Expects.ConditionalEvent(!bindsLate, x => x.BreakpointChangedEvent(BreakpointReason.Changed, 12)) .AfterSetBreakpoints(callingBreakpoints); this.Comment("Set a function breakpoint in a class member, expect it to be placed at the opening bracket"); runner.Expects.ConditionalEvent(!bindsLate, x => x.FunctionBreakpointChangedEvent(BreakpointReason.Changed, startLine: 47, endLine: 48)) .AfterSetFunctionBreakpoints(functionBreakpoints); this.Comment("Set a function breakpoint in a non-member, expect it to be placed on the first line of code"); functionBreakpoints.Add("a()"); runner.Expects.ConditionalEvent(!bindsLate, x => x.FunctionBreakpointChangedEvent(BreakpointReason.Changed, startLine: 42, endLine: 43)) .AfterSetFunctionBreakpoints(functionBreakpoints); runner.Expects.ConditionalEvent(bindsLate, x => x.BreakpointChangedEvent(BreakpointReason.Changed, 12) .FunctionBreakpointChangedEvent(BreakpointReason.Changed, startLine: 47, endLine: 48) .FunctionBreakpointChangedEvent(BreakpointReason.Changed, startLine: 42, endLine: 43)) .ExitedEvent() .TerminatedEvent() .AfterConfigurationDone(); runner.DisconnectAndVerify(); } }
public void WatchBasic(ITestSettings settings) { this.TestPurpose("Evaluate some expressions in watch."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a line breakpoints so that we can stop."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 31)); this.Comment("To start debugging and break"); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("To evaluate variables and functions in watch."); string evalMyInt = currentFrame.Evaluate("myint-=100", EvaluateContext.Watch); currentFrame.AssertEvaluateAsChar("mychar", EvaluateContext.Watch, 'A'); string evalMyBool = currentFrame.Evaluate("mybool", EvaluateContext.Watch); currentFrame.AssertEvaluateAsWChar("mywchar", EvaluateContext.Watch, 'z'); currentFrame.AssertEvaluateAsDouble("mydouble", EvaluateContext.Watch, 321); currentFrame.AssertEvaluateAsFloat("myfloat", EvaluateContext.Watch, 299); string evalFuncMaxInt = currentFrame.Evaluate("Test::max(myint,1)", EvaluateContext.Watch); currentFrame.AssertEvaluateAsDouble("Test::max(mydouble,0.0)-321.0", EvaluateContext.Watch, 0); Assert.Equal("0", evalMyInt); Assert.Equal("true", evalMyBool); Assert.Equal("1", evalFuncMaxInt); } this.Comment("Run to completion"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void AssignInvalidExpressionToVariable(ITestSettings settings) { this.TestPurpose("Assign an invalid expression to a variable."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a breakpoint so that we can stop at a line."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 31)); this.Comment("Start debugging and hit breakpoint."); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Assign an invalid expression to a variable."); currentFrame.GetVariable("myint").SetVariableValueExpectFailure("39+nonexistingint"); } // Start another inspector to refresh values using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Check the value of the variable hasn't been updated."); Assert.Equal("100", currentFrame.GetVariable("myint").Value); } this.Comment("Continue to run to exist."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void ExecutionAsyncBreak(ITestSettings settings) { this.TestPurpose("Verify break all should work run function"); this.WriteSettings(settings); this.Comment("Open the kitchen sink debuggee for execution tests."); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Execution); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fNonTerminating", "-fCalling"); this.Comment("Try to break all"); StoppedEvent breakAllEvent = new StoppedEvent(StoppedReason.Pause); runner.Expects.Event(breakAllEvent).AfterAsyncBreak(); this.WriteLine("Break all stopped on:"); this.WriteLine(breakAllEvent.ActualEvent.ToString()); this.Comment("Set a breakpoint while breaking code"); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.NonTerminating, 28)); this.Comment("Start running after the async break and then hit the breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.NonTerminating, 28).AfterContinue(); this.Comment("Evaluate the shouldExit member to true to stop the infinite loop."); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector firstFrame = threadInspector.Stack.First(); this.WriteLine(firstFrame.ToString()); firstFrame.GetVariable("shouldExit").Value = "true"; } this.Comment("Continue running at the end of application"); runner.Expects.ExitedEvent().TerminatedEvent().AfterContinue(); this.Comment("Verify debugger and debuggee closed"); runner.DisconnectAndVerify(); } }
public void DuplicateBreakpoints(ITestSettings settings) { this.TestPurpose("Tests that duplicate breakpoints are only hit once"); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Breakpoint); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fCalling"); // These two breakpoints should resolve to the same line - setting two breakpoints on the same // line directly will throw an exception. SourceBreakpoints callingBreakpoints = debuggee.Breakpoints(SinkHelper.Calling, 11, 12); this.Comment("Set two line breakpoints that resolve to the same source location"); runner.SetBreakpoints(callingBreakpoints); this.Comment("Set duplicate function breakpoints"); FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("Arguments::CoreRun", "Arguments::CoreRun"); runner.SetFunctionBreakpoints(functionBreakpoints); this.Comment("Run to first breakpoint"); runner.ExpectBreakpointAndStepToTarget(SinkHelper.Arguments, startLine: 9, targetLine: 10) .AfterConfigurationDone(); this.Comment("Run to second breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.Calling, 12) .AfterContinue(); this.Comment("Run to completion"); runner.Expects.ExitedEvent() .TerminatedEvent() .AfterContinue(); runner.DisconnectAndVerify(); } }
public void ExecutionStepRecursiveCall(ITestSettings settings) { this.TestPurpose("Verify steps should work when debugging recursive call"); this.WriteSettings(settings); this.Comment("Open the kitchen sink debuggee for execution tests."); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Execution); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fCalling"); this.Comment("Set initial function breakpoints"); FunctionBreakpoints funcBp = new FunctionBreakpoints("Calling::CoreRun()"); runner.SetFunctionBreakpoints(funcBp); this.Comment("Launch and run until hit function breakpoint in the entry of calling"); runner.ExpectBreakpointAndStepToTarget(SinkHelper.Calling, startLine: 47, targetLine: 48).AfterConfigurationDone(); this.Comment("Step over to go to the entry of recursive call"); runner.Expects.HitStepEvent(SinkHelper.Calling, 49).AfterStepOver(); this.Comment("Step in the recursive call"); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, startLine: 25, targetLine: 26).AfterStepIn(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Set count = 2"); IFrameInspector currentFrame = threadInspector.Stack.First(); currentFrame.GetVariable("count").Value = "2"; this.Comment("Verify there is only one 'recursiveCall' frames"); threadInspector.AssertStackFrameNames(true, "recursiveCall.*", "Calling::CoreRun.*", "Feature::Run.*", "main.*"); } this.Comment("Step over and then step in the recursive call once again"); runner.Expects.HitStepEvent(SinkHelper.Calling, 29).AfterStepOver(); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, startLine: 25, targetLine: 26).AfterStepIn(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Verify there are two 'recursiveCall' frames"); threadInspector.AssertStackFrameNames(true, "recursiveCall.*", "recursiveCall.*", "Calling::CoreRun.*", "Feature::Run.*", "main.*"); this.Comment("Set a source breakpoint in recursive call"); SourceBreakpoints srcBp = debuggee.Breakpoints(SinkHelper.Calling, 26); runner.SetBreakpoints(srcBp); } this.Comment("Step over the recursive call and hit the source breakpoint"); runner.Expects.HitStepEvent(SinkHelper.Calling, 29).AfterStepOver(); runner.Expects.HitBreakpointEvent(SinkHelper.Calling, 26).AfterStepOver(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Verify there are three 'recursiveCall' frames"); threadInspector.AssertStackFrameNames(true, "recursiveCall.*", "recursiveCall.*", "recursiveCall.*", "Calling::CoreRun.*", "Feature::Run.*", "main.*"); } this.Comment("Try to step out twice from recursive call"); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, 29, 30).AfterStepOut(); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, 29, 30).AfterStepOut(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Verify 'recursiveCall' return back only one frame"); threadInspector.AssertStackFrameNames(true, "recursiveCall.*", "Calling::CoreRun.*", "Feature::Run.*", "main.*"); } this.Comment("Step over from recursive call"); runner.ExpectStepAndStepToTarget(SinkHelper.Calling, 49, 50).AfterStepOver(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Verify there is not 'recursiveCall' frame"); threadInspector.AssertStackFrameNames(true, "Calling::CoreRun.*", "Feature::Run.*", "main.*"); } this.Comment("Verify stop debugging"); runner.DisconnectAndVerify(); } }
public void RaisedHandledException(ITestSettings settings) { this.TestPurpose("This test checks to see if user handled exception can work during debugging"); this.WriteSettings(settings); this.Comment("Set initial debuggee for application"); IDebuggee debuggee = OpenDebuggee(this, settings, DebuggeeMonikers.Exception.Default); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Launch the application"); runner.Launch(settings.DebuggerSettings, debuggee, "-CallRaisedHandledException"); this.Comment("Set line breakpoints to the lines with entry of try block and catch block"); SourceBreakpoints bps = debuggee.Breakpoints(srcClassName, 20, 33); runner.SetBreakpoints(bps); this.Comment("Start debugging and hit the breakpoint in the try block"); runner.Expects.HitBreakpointEvent(srcClassName, 20).AfterConfigurationDone(); this.Comment("Step over in the try block"); runner.Expects.HitStepEvent(srcClassName, 21).AfterStepOver(); this.Comment("Continue to raise the exception and hit the breakpoint set in the catch block"); runner.Expects.HitBreakpointEvent(srcClassName, 33).AfterContinue(); this.Comment("Verify can step over in the catch block"); runner.Expects.HitStepEvent(srcClassName, 34).AfterStepOver(); this.Comment("Verify the callstack, variables and evaluation "); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Get current frame object"); IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify current frame when stop at the catch block"); threadInspector.AssertStackFrameNames(true, "myException::RaisedHandledException.*"); this.Comment("Verify the variables in the catch block"); Assert.Subset(new HashSet <string>() { "result", "global", "this", "a", "errorCode", "ex" }, currentFrame.Variables.ToKeySet()); currentFrame.AssertVariables("result", "201", "global", "101", "a", "100"); this.Comment("Verify the exception information in the catch block"); IVariableInspector exVar = currentFrame.Variables["ex"]; Assert.Contains("code", exVar.Variables.Keys); this.WriteLine("Expected: 101, Actual: {0}", exVar.Variables["code"].Value); Assert.Equal("101", exVar.Variables["code"].Value); // TODO: LLDB was affected by bug #240441, I wil update this once this bug get fixed if (settings.DebuggerSettings.DebuggerType != SupportedDebugger.Lldb) { this.Comment("Evaluate an expression and verify the results"); string varEvalResult = currentFrame.Evaluate("result=result + 1"); this.WriteLine("Expected: 202, Actual: {0}", varEvalResult); Assert.Equal("202", varEvalResult); } this.Comment("Evaluate a function and verify the the results"); // TODO: Mingw32 was affected by bug #242924, I wil update this once this bug get fixed bool evalNotSupportedInCatch = (settings.DebuggerSettings.DebuggerType == SupportedDebugger.Gdb_MinGW && settings.DebuggerSettings.DebuggeeArchitecture == SupportedArchitecture.x86) || (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg && settings.DebuggerSettings.DebuggeeArchitecture == SupportedArchitecture.x64); if (!evalNotSupportedInCatch) { string funEvalResult = currentFrame.Evaluate("RecursiveFunc(50)"); this.WriteLine("Expected: 1, Actual: {0}", funEvalResult); Assert.Equal("1", funEvalResult); } } this.Comment("Verify can step over after evaluation in the catch block"); runner.Expects.HitStepEvent(srcClassName, 35).AfterStepOver(); this.Comment("Continue to run at the end of the application"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
/// <summary> /// Testing the common targeted scenarios /// </summary> private void RunTargetedScenarios(ITestSettings settings, string outputName, int debuggeeMoniker) { this.Comment("Set initial debuggee"); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, debuggeeName, debuggeeMoniker, outAppName); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); this.Comment("Set initial function breakpoints"); FunctionBreakpoints functionBreakpoints = new FunctionBreakpoints("main", "myClass::DisplayName", "myClass::DisplayAge"); runner.SetFunctionBreakpoints(functionBreakpoints); this.Comment("Set line breakpoints to the lines with entry of shared library"); SourceBreakpoints bps = debuggee.Breakpoints(srcAppName, 71, 77); runner.SetBreakpoints(bps); this.Comment("Launch and run until first breakpoint in the entry of main"); runner.ExpectBreakpointAndStepToTarget(srcAppName, startLine: 62, targetLine: 63) .AfterConfigurationDone(); this.Comment("Continue to go to the line which is the first entry of shared library"); runner.Expects.HitBreakpointEvent(srcAppName, 71) .AfterContinue(); this.Comment("Step into the function in shared library"); runner.Expects.HitStepEvent(srcLibName, 23) .AfterStepIn(); this.Comment("Step out to go back to the entry in main function"); runner.Expects.HitStepEvent(srcAppName, 71) .AfterStepOut(); this.Comment("Step over to go to the line which is the second entry of shared library"); runner.Expects.HitStepEvent(srcAppName, 73).AfterStepOver(); this.Comment("Step over a function which have a breakpoint set in shared library"); runner.ExpectBreakpointAndStepToTarget(srcLibName, startLine: 8, targetLine: 9).AfterStepOver(); this.Comment("Step over a line in function which is inside shared library"); runner.Expects.HitStepEvent(srcLibName, 10).AfterStepOver(); this.Comment("Step out to go back to the entry in main function"); runner.ExpectStepAndStepToTarget(srcAppName, startLine: 73, targetLine: 75).AfterStepOut(); this.Comment("Continue to hit breakpoint in function which is inside shared library"); runner.ExpectBreakpointAndStepToTarget(srcLibName, startLine: 15, targetLine: 16) .AfterContinue(); this.Comment("Continue to hit breakpoint which set in the last entry of shared library"); runner.Expects.HitBreakpointEvent(srcAppName, 77).AfterContinue(); this.Comment("Step over a function which don't have breakpoint set in shared library"); runner.Expects.HitStepEvent(srcAppName, 79) .AfterStepOver(); this.Comment("Continue to run till at the end of the application"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void ThreadingBasic(ITestSettings settings) { this.TestPurpose("Test basic multithreading scenario."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Threading); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Launching debuggee. Run until multiple threads are running."); runner.Launch(settings.DebuggerSettings, debuggee, "-fThreading"); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Threading, 37)); runner.Expects.HitBreakpointEvent() .AfterConfigurationDone(); IEnumerable <IThreadInfo> threads = runner.GetThreads(); List <string> loopCounts = new List <string>(); this.Comment("Inspect threads and find 'loopCount' variable on each worker thread."); this.WriteLine("Threads:"); foreach (var threadInfo in threads) { IThreadInspector threadInspector = threadInfo.GetThreadInspector(); // Don't look at main thread, just workers if (threadInspector.ThreadId == runner.StoppedThreadId) { continue; } this.Comment("Thread '{0}', Id: {1}".FormatInvariantWithArgs(threadInfo.Name, threadInspector.ThreadId)); IFrameInspector threadLoopFrame = threadInspector.Stack.FirstOrDefault(s => s.Name.Contains("ThreadLoop")); // Fail the test if the ThreadLoop frame could not be found if (threadLoopFrame == null) { this.WriteLine("This thread's stack did not contain a frame with 'ThreadLoop'"); this.WriteLine("Stack Trace:"); foreach (var frame in threadInspector.Stack) { this.WriteLine(frame.Name); } continue; } string variables = threadLoopFrame.Variables.ToReadableString(); this.WriteLine("Variables in 'ThreadLoop' frame:"); this.WriteLine(variables); // Put the different loopCounts in a list, so they can be verified order agnostic string loopCountValue = threadLoopFrame.GetVariable("loopCount").Value; this.WriteLine("loopCount = {0}", loopCountValue); loopCounts.Add(loopCountValue); } //Verify all the worker threads were observed Assert.True(loopCounts.Contains("0"), "Could not find thread with loop count 0"); Assert.True(loopCounts.Contains("1"), "Could not find thread with loop count 1"); Assert.True(loopCounts.Contains("2"), "Could not find thread with loop count 2"); Assert.True(loopCounts.Contains("3"), "Could not find thread with loop count 3"); Assert.True(4 == loopCounts.Count, "Expected to find 4 threads, but found " + loopCounts.Count.ToString(CultureInfo.InvariantCulture)); this.Comment("Run to end."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void TestFolderol(ITestSettings settings) { this.TestPurpose("This test checks a bunch of commands and events."); this.WriteSettings(settings); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, HelloName, DebuggeeMonikers.HelloWorld.Sample); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Launch the debuggee"); runner.Launch(settings.DebuggerSettings, debuggee); StoppedEvent stopAtBreak = new StoppedEvent(StoppedReason.Breakpoint); // VsDbg does not fire Breakpoint Change events when breakpoints are set. // Instead it sends a new breakpoint event when it is bound (after configuration done). bool bindsLate = (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg); this.Comment("Set a breakpoint on line 8, but expect it to resolve to line 9."); runner.Expects.ConditionalEvent(!bindsLate, x => x.BreakpointChangedEvent(BreakpointReason.Changed, 9)) .AfterSetBreakpoints(debuggee.Breakpoints(HelloSourceName, 8)); this.Comment("Start debuggging until breakpoint is hit."); runner.Expects.ConditionalEvent(bindsLate, x => x.BreakpointChangedEvent(BreakpointReason.Changed, 9)) .Event(stopAtBreak) .AfterConfigurationDone(); Assert.Equal(HelloSourceName, stopAtBreak.ActualEventInfo.Filename); Assert.Equal(9, stopAtBreak.ActualEventInfo.Line); Assert.Equal(StoppedReason.Breakpoint, stopAtBreak.ActualEventInfo.Reason); this.Comment("Step forward twice until we have initialized variables"); runner.Expects.StoppedEvent(StoppedReason.Step, HelloSourceName, 10) .AfterStepOver(); runner.Expects.StoppedEvent(StoppedReason.Step, HelloSourceName, 11) .AfterStepIn(); this.Comment("Inspect the stack and try evaluation."); using (IThreadInspector inspector = runner.GetThreadInspector()) { this.Comment("Get the stack trace"); IFrameInspector mainFrame = inspector.Stack.First(); inspector.AssertStackFrameNames(true, "main.*"); this.WriteLine("Main frame: {0}", mainFrame); this.Comment("Get variables"); Assert.Subset(new HashSet <string>() { "x", "y", "argc", "argv" }, mainFrame.Variables.ToKeySet()); mainFrame.AssertVariables( "x", "6", "argc", "1"); IVariableInspector argv = mainFrame.Variables["argv"]; Assert.Matches(HexNumberPattern, argv.Value); this.Comment("Expand a variable (argv has *argv under it)"); string variableName = "*argv"; if (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg) { variableName = String.Empty; } Assert.Contains(variableName, argv.Variables.Keys); Assert.Matches(HexNumberPattern, argv.Variables[variableName].Value); this.Comment("Evaluate with side effect"); string result = mainFrame.Evaluate("x = x + 1"); Assert.Equal("7", result); } this.Comment("Step to force stack info to refresh"); runner.Expects.StoppedEvent(StoppedReason.Step).AfterStepOver(); using (IThreadInspector inspector = runner.GetThreadInspector()) { this.Comment("Evaluation has side effect, make sure it propagates"); Assert.Equal("7", inspector.Stack.First().Variables["x"].Value); } runner.Expects.ExitedEvent(0).TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void EvaluateOnFrames(ITestSettings settings) { this.TestPurpose("To check evalution on different frame with different variable types."); this.WriteSettings(settings); this.Comment("Open the debugge with a initialization."); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("Set a breakpoint so that we can stop at a line."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 19)); this.Comment("To start debugging and break"); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame; this.Comment("To evaluate on the first frame."); currentFrame = threadInspector.Stack.First(); currentFrame.AssertVariables("isCalled", "true"); Assert.Equal("true", currentFrame.Evaluate("isCalled||false", EvaluateContext.Watch)); currentFrame.AssertEvaluateAsDouble("d", EvaluateContext.Watch, 10.1); this.Comment("Switch to next frame then evaluate on that frame."); currentFrame = threadInspector.Stack.ElementAt(1); currentFrame.GetVariable("_f").AssertValueAsFloat(1); currentFrame.AssertEvaluateAsFloat("_f", EvaluateContext.Watch, 1); this.Comment("To evaluate string and vector type on it, the try to enable pretty printing to evaluate again."); currentFrame = threadInspector.Stack.ElementAt(2); currentFrame.GetVariable("vec").AssertValueAsVector(5); currentFrame.AssertEvaluateAsVector("vec", EvaluateContext.Watch, 5); this.Comment("To evaluate some special values on the fourth frame."); currentFrame = threadInspector.Stack.ElementAt(3); currentFrame.AssertEvaluateAsDouble("mydouble=1.0", EvaluateContext.Watch, 1); currentFrame.GetVariable("mynull").AssertValueAsChar('\0'); this.Comment("To evaluate class on stack on the fifth frame."); currentFrame = threadInspector.Stack.ElementAt(4); IVariableInspector varInspector; varInspector = currentFrame.GetVariable("student"); Assert.Equal("10", varInspector.GetVariable("age").Value); Assert.Equal("19", currentFrame.Evaluate("student.age=19", EvaluateContext.Watch)); this.Comment("To evaluate array on the sixth frame."); currentFrame = threadInspector.Stack.ElementAt(5); Assert.Equal("10", currentFrame.Evaluate("*(pArr+1)=10", EvaluateContext.Watch)); Assert.Equal("100", currentFrame.Evaluate("arr[0]=100", EvaluateContext.Watch)); } this.Comment("Continue to run to exist."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void DataTipBasic(ITestSettings settings) { this.TestPurpose("To test evaluation in datatip."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Expression); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch."); runner.Launch(settings.DebuggerSettings, debuggee, "-fExpression"); this.Comment("To set a breakpoint so that we can stop at somewhere for evaluation."); runner.SetBreakpoints(debuggee.Breakpoints(SinkHelper.Expression, 19)); this.Comment("To start debugging and break"); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IFrameInspector currentFrame; this.Comment("To evaluate in datatip on the first frame."); currentFrame = threadInspector.Stack.First(); Assert.Equal("true", currentFrame.Evaluate("isCalled", EvaluateContext.DataTip)); currentFrame.AssertEvaluateAsDouble("d", EvaluateContext.DataTip, 10.1); // We only verify the major contents in datatip Assert.Contains(@"accumulate(int)", currentFrame.Evaluate("accumulate", EvaluateContext.DataTip), StringComparison.Ordinal); this.Comment("To evaluate in datatip on the fourth frame."); currentFrame = threadInspector.Stack.ElementAt(3); currentFrame.AssertEvaluateAsDouble("mydouble", EvaluateContext.DataTip, double.PositiveInfinity); currentFrame.AssertEvaluateAsChar("mynull", EvaluateContext.DataTip, '\0'); this.Comment("To evaluate in datatip on the fifth frame."); currentFrame = threadInspector.Stack.ElementAt(4); currentFrame.AssertEvaluateAsObject("student", EvaluateContext.DataTip, "name", @"""John""", "age", "10"); Assert.Matches(@"0x[0-9A-Fa-f]+", currentFrame.Evaluate("pStu", EvaluateContext.DataTip)); this.Comment("To evaluate in datatip on the sixth frame."); currentFrame = threadInspector.Stack.ElementAt(5); currentFrame.AssertEvaluateAsIntArray("arr", EvaluateContext.DataTip, 0, 1, 2, 3, 4); Assert.Matches(@"0x[0-9A-Fa-f]+", currentFrame.Evaluate("pArr", EvaluateContext.DataTip)); this.Comment("To evaluate in datatip on the seventh frame."); currentFrame = threadInspector.Stack.ElementAt(6); Assert.Equal("true", currentFrame.Evaluate("mybool", EvaluateContext.DataTip)); Assert.Equal("100", currentFrame.Evaluate("myint", EvaluateContext.DataTip)); currentFrame.AssertEvaluateAsFloat("myfloat", EvaluateContext.DataTip, 299); currentFrame.AssertEvaluateAsDouble("mydouble", EvaluateContext.DataTip, 321); currentFrame.AssertEvaluateAsChar("mychar", EvaluateContext.DataTip, 'A'); currentFrame.AssertEvaluateAsWChar("mywchar", EvaluateContext.DataTip, 'z'); } this.Comment("Continue to run to exist."); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void LineBreakpointsBasic(ITestSettings settings) { this.TestPurpose("Tests basic operation of line breakpoints"); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Breakpoint); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fCalling"); // These keep track of all the breakpoints in a source file SourceBreakpoints argumentsBreakpoints = debuggee.Breakpoints(SinkHelper.Arguments, 23); SourceBreakpoints mainBreakpoints = debuggee.Breakpoints(SinkHelper.Main, 33); SourceBreakpoints callingBreakpoints = debuggee.Breakpoints(SinkHelper.Calling, 48); // A bug in clang causes several breakpoint hits in a constructor // See: https://llvm.org/bugs/show_bug.cgi?id=30620 if (settings.CompilerSettings.CompilerType != SupportedCompiler.ClangPlusPlus) { callingBreakpoints.Add(6); } this.Comment("Set initial breakpoints"); runner.SetBreakpoints(argumentsBreakpoints); runner.SetBreakpoints(mainBreakpoints); runner.SetBreakpoints(callingBreakpoints); this.Comment("Launch and run until first breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.Arguments, 23) .AfterConfigurationDone(); // A bug in clang causes several breakpoint hits in a constructor // See: https://llvm.org/bugs/show_bug.cgi?id=30620 if (settings.CompilerSettings.CompilerType != SupportedCompiler.ClangPlusPlus) { this.Comment("Continue until second initial breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.Calling, 6).AfterContinue(); } this.Comment("Disable third initial breakpoint"); mainBreakpoints.Remove(33); runner.SetBreakpoints(mainBreakpoints); this.Comment("Continue, hit fourth initial breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.Calling, 48).AfterContinue(); this.Comment("Set a breakpoint while in break mode"); callingBreakpoints.Add(52); runner.SetBreakpoints(callingBreakpoints); this.Comment("Continue until newly-added breakpoint"); runner.Expects.HitBreakpointEvent(SinkHelper.Calling, 52) .AfterContinue(); this.Comment("Continue until end"); runner.Expects.ExitedEvent() .TerminatedEvent() .AfterContinue(); runner.DisconnectAndVerify(); } }
public void MapDirectory(ITestSettings settings) { this.TestPurpose("Validate Source Mapping."); this.WriteSettings(settings); IDebuggee debuggee = SourceMappingHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.SourceMapping.Default); // VsDbg is case insensitive on Windows so sometimes stackframe file names might all be lowercase StringComparison comparison = settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure"); LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, false, "-fCalling"); launch.Args.externalConsole = false; this.Comment("Setting up Source File Mappings"); Dictionary <string, string> sourceMappings = new Dictionary <string, string>(); string pathRoot = Path.GetPathRoot(debuggee.SourceRoot); string mgrDirectoryMapping = Path.Combine(debuggee.SourceRoot, SourceMappingHelper.Manager, Path.GetRandomFileName()); string writerDirectoryMapping = Path.Combine(pathRoot, Path.GetRandomFileName(), Path.GetRandomFileName()); string rootDirectoryMapping = Path.Combine(pathRoot, Path.GetRandomFileName()); sourceMappings.Add(Path.Combine(debuggee.SourceRoot, SourceMappingHelper.WriterFolder), writerDirectoryMapping); sourceMappings.Add(Path.Combine(debuggee.SourceRoot, SourceMappingHelper.ManagerFolder), mgrDirectoryMapping); sourceMappings.Add(debuggee.SourceRoot, rootDirectoryMapping); launch.Args.sourceFileMap = sourceMappings; try { if (PlatformUtilities.IsWindows) { // Create all the directories but only some of the files will exist on disk. foreach (var dir in sourceMappings.Values) { Directory.CreateDirectory(dir); } File.Copy(Path.Combine(debuggee.SourceRoot, SourceMappingHelper.WriterFolder, SourceMappingHelper.Writer), Path.Combine(writerDirectoryMapping, SourceMappingHelper.Writer), true); File.Copy(Path.Combine(debuggee.SourceRoot, SourceMappingHelper.Main), Path.Combine(rootDirectoryMapping, SourceMappingHelper.Main), true); } runner.RunCommand(launch); this.Comment("Set Breakpoint"); SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(SourceMappingHelper.Writer, 9); SourceBreakpoints managerBreakpoints = debuggee.Breakpoints(SourceMappingHelper.Manager, 8); runner.SetBreakpoints(writerBreakpoints); runner.SetBreakpoints(managerBreakpoints); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IEnumerator <IFrameInspector> frameEnumerator = threadInspector.Stack.GetEnumerator(); // Move to first stack item Assert.True(frameEnumerator.MoveNext()); this.Comment(string.Format(CultureInfo.InvariantCulture, "Verify source path for {0}.", SourceMappingHelper.Writer)); // Since file is there, lowercase the drive letter ValidateMappingToFrame(SourceMappingHelper.Writer, EnsureDriveLetterLowercase(Path.Combine(writerDirectoryMapping, SourceMappingHelper.Writer)), frameEnumerator.Current, comparison); // Move to second stack item Assert.True(frameEnumerator.MoveNext()); this.Comment(string.Format(CultureInfo.InvariantCulture, "Verify source path for {0}.", SourceMappingHelper.Main)); // Since file is there, lowercase the drive letter ValidateMappingToFrame(SourceMappingHelper.Main, EnsureDriveLetterLowercase(Path.Combine(rootDirectoryMapping, SourceMappingHelper.Main)), frameEnumerator.Current, comparison); } runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterContinue(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IEnumerator <IFrameInspector> frameEnumerator = threadInspector.Stack.GetEnumerator(); // Move to first stack item Assert.True(frameEnumerator.MoveNext()); this.Comment(string.Format(CultureInfo.InvariantCulture, "Verify source path for {0}.", SourceMappingHelper.Manager)); // Since file is not there, keep what was passed in ValidateMappingToFrame(SourceMappingHelper.Manager, EnsureDriveLetterLowercase(Path.Combine(mgrDirectoryMapping, SourceMappingHelper.Manager)), frameEnumerator.Current, comparison); // Move to second stack item Assert.True(frameEnumerator.MoveNext()); this.Comment(string.Format(CultureInfo.InvariantCulture, "Verify source path for {0}.", SourceMappingHelper.Main)); // Since file is there, lowercase the drive letter ValidateMappingToFrame(SourceMappingHelper.Main, EnsureDriveLetterLowercase(Path.Combine(rootDirectoryMapping, SourceMappingHelper.Main)), frameEnumerator.Current, comparison); } writerBreakpoints.Remove(9); managerBreakpoints.Remove(8); runner.SetBreakpoints(writerBreakpoints); runner.SetBreakpoints(managerBreakpoints); this.Comment("Continue to end"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } finally { if (PlatformUtilities.IsWindows) { foreach (var dir in sourceMappings.Values) { if (Directory.Exists(dir)) { Directory.Delete(dir, recursive: true); } } } } } }
public void TestOptimizedSharedLib(ITestSettings settings) { this.TestPurpose("Tests basic bps and source information for shared library"); this.WriteSettings(settings); IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, Name, DebuggeeMonikers.Optimization.OptimizationWithSymbols); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee); SourceBreakpoints mainBreakpoints = debuggee.Breakpoints(SourceName, 87, 89); SourceBreakpoints libBreakpoints = debuggee.Breakpoints(SrcLibName, 9, 12); this.Comment("Set initial breakpoints"); runner.SetBreakpoints(mainBreakpoints); runner.SetBreakpoints(libBreakpoints); this.Comment("Launch and run until 1st bp"); runner.Expects.HitBreakpointEvent(SourceName, 87) .AfterConfigurationDone(); //Todo: this has different behavior on Mac, I have logged bug#247895 to track //Del said that Different compilers generate symbols differently. //Our tests have to be resilient to this fact. The location of the step is reasonable, //so this is by design. this.Comment("enter into the library source"); runner.ExpectBreakpointAndStepToTarget(SrcLibName, 8, 9).AfterContinue(); this.Comment("Step over"); runner.Expects.HitStepEvent(SrcLibName, 10).AfterStepOver(); this.Comment("Check the un-optimized values in shared library"); using (IThreadInspector inspector = runner.GetThreadInspector()) { IFrameInspector currentFrame = inspector.Stack.First(); IVariableInspector age = currentFrame.Variables["age"]; this.Comment("Check the local variable in sub function"); Assert.Matches("31", age.Value); this.Comment("run to continue"); if (settings.DebuggerSettings.DebuggerType == SupportedDebugger.Lldb) { runner.Expects.HitBreakpointEvent(SourceName, 89) .AfterContinue(); this.Comment("Verify current frame for main func"); inspector.AssertStackFrameNames(true, "main"); } else { runner.Expects.HitBreakpointEvent(SrcLibName, 12) .AfterContinue(); this.Comment("Verify current frame for library func"); inspector.AssertStackFrameNames(true, "myClass::DisplayAge"); this.Comment("Step out to main entry"); runner.Expects.HitBreakpointEvent(SourceName, 89).AfterContinue(); this.Comment("Verify current frame for main entry"); inspector.AssertStackFrameNames(true, "main"); } this.Comment("Evaluate the expression:"); //skip the Mac's verification as bug#247893 currentFrame = inspector.Stack.First(); string strAge = currentFrame.Evaluate("myclass->DisplayAge(30)"); if (settings.DebuggerSettings.DebuggerType == SupportedDebugger.Gdb_MinGW || settings.DebuggerSettings.DebuggerType == SupportedDebugger.Gdb_Cygwin) { Assert.Equal("Cannot evaluate function -- may be inlined", strAge); } } runner.DisconnectAndVerify(); } }
public void RaisedReThrowException(ITestSettings settings) { this.TestPurpose("This test checks to see if re-throw exception can work during debugging."); this.WriteSettings(settings); this.Comment("Set initial debuggee for application"); IDebuggee debuggee = OpenDebuggee(this, settings, DebuggeeMonikers.Exception.Default); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Launch the application"); runner.Launch(settings.DebuggerSettings, debuggee, "-CallRaisedReThrowException"); this.Comment("Set line breakpoints to the lines with entry of try block and catch block"); SourceBreakpoints bps = debuggee.Breakpoints(srcClassName, 73, 79, 86); runner.SetBreakpoints(bps); this.Comment("Start debugging and hit the breakpoint in the try block"); runner.Expects.HitBreakpointEvent(srcClassName, 73).AfterConfigurationDone(); this.Comment("Continue executing and hit the breakpoint in the frist catch block"); runner.Expects.HitBreakpointEvent(srcClassName, 79).AfterContinue(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Get current frame object"); IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify current frame when stop at the first catch block"); threadInspector.AssertStackFrameNames(true, "myException::RaisedReThrowException.*"); this.Comment("Verify the variables of 'errorCode' in the first catch block"); currentFrame.AssertVariables("errorCode", "200"); this.Comment("Verify step in can work in the first catch block"); runner.ExpectStepAndStepToTarget(srcClassName, startLine: 41, targetLine: 42).AfterStepIn(); this.Comment("Verify current frame after step in another function"); threadInspector.AssertStackFrameNames(true, "myException::EvalFunc.*"); this.Comment("Verify step out can work in the first catch block"); runner.Expects.HitStepEvent(srcClassName, 79).AfterStepOut(); } this.Comment("Continue to hit the re-throw exception in the first catch block"); runner.Expects.HitBreakpointEvent(srcClassName, 86).AfterContinue(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Get current frame object"); IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify current frame when stop at the second catch block"); threadInspector.AssertStackFrameNames(true, "myException::RaisedReThrowException.*"); this.Comment("Verify the variables in the second catch block"); Assert.Subset(new HashSet <string>() { "var", "this", "errorCode", "ex2" }, currentFrame.Variables.ToKeySet()); currentFrame.AssertVariables("var", "400", "errorCode", "400"); this.Comment("Verify the exception information in the second catch block"); IVariableInspector ex2Var = currentFrame.Variables["ex2"]; Assert.Contains("code", ex2Var.Variables.Keys); this.WriteLine("Expected: 400, Actual: {0}", ex2Var.Variables["code"].Value); Assert.Equal("400", ex2Var.Variables["code"].Value); this.Comment("Evaluate a function and verify the the results at the second catch block "); // TODO: Mingw32 was affected by bug #242924, I wil update this once this bug get fixed bool evalNotSupportedInCatch = (settings.DebuggerSettings.DebuggerType == SupportedDebugger.Gdb_MinGW && settings.DebuggerSettings.DebuggeeArchitecture == SupportedArchitecture.x86) || (settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg && settings.DebuggerSettings.DebuggeeArchitecture == SupportedArchitecture.x64); if (!evalNotSupportedInCatch) { string funEvalResult = currentFrame.Evaluate("EvalFunc(20,20)"); this.WriteLine("Expected: 40, Actual: {0}", funEvalResult); Assert.Equal("40", funEvalResult); } } this.Comment("Verify can step out from a catch block"); runner.ExpectStopAndStepToTarget(StoppedReason.Step, srcAppName, startLine: 61, targetLine: 64).AfterStepOut(); this.Comment("Continue to run at the end of the application"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } }
public void MapSpecificFile(ITestSettings settings) { this.TestPurpose("Validate Specific File Mapping."); this.WriteSettings(settings); IDebuggee debuggee = SourceMappingHelper.Open(this, settings.CompilerSettings, DebuggeeMonikers.SourceMapping.Default); // VsDbg is case insensitive on Windows so sometimes stackframe file names might all be lowercase StringComparison comparison = settings.DebuggerSettings.DebuggerType == SupportedDebugger.VsDbg ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure"); LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, false); launch.Args.externalConsole = false; this.Comment("Setting up Source File Mappings"); Dictionary <string, string> sourceMappings = new Dictionary <string, string>(); string pathRoot = Path.GetPathRoot(debuggee.SourceRoot); string sourceFileMapping = Path.Combine(pathRoot, Path.GetRandomFileName(), SourceMappingHelper.Writer); string compileFileMapping = Path.Combine(debuggee.SourceRoot, SourceMappingHelper.WriterFolder, SourceMappingHelper.Writer); if (PlatformUtilities.IsWindows) { // Move file to the location Directory.CreateDirectory(Path.GetDirectoryName(sourceFileMapping)); File.Copy(compileFileMapping, sourceFileMapping, true); } // Drive letter should be lowercase sourceMappings.Add(compileFileMapping, sourceFileMapping); launch.Args.sourceFileMap = sourceMappings; try { runner.RunCommand(launch); this.Comment("Set Breakpoint"); SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(SourceMappingHelper.Writer, 9); runner.SetBreakpoints(writerBreakpoints); runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { IEnumerator <IFrameInspector> frameEnumerator = threadInspector.Stack.GetEnumerator(); // Move to first stack item Assert.True(frameEnumerator.MoveNext()); this.Comment("Verify path is changed for writer.cpp frame"); ValidateMappingToFrame(SourceMappingHelper.Writer, EnsureDriveLetterLowercase(sourceFileMapping), frameEnumerator.Current, comparison); // Move to second stack item Assert.True(frameEnumerator.MoveNext()); this.Comment("Verify path is not changed for main.cpp frame."); ValidateMappingToFrame(SourceMappingHelper.Main, EnsureDriveLetterLowercase(Path.Combine(debuggee.SourceRoot, SourceMappingHelper.Main)), frameEnumerator.Current, comparison); writerBreakpoints.Remove(9); runner.SetBreakpoints(writerBreakpoints); this.Comment("Continue to end"); runner.Expects.TerminatedEvent().AfterContinue(); runner.DisconnectAndVerify(); } } finally { if (PlatformUtilities.IsWindows) { // Cleanup the directory if (Directory.Exists(Path.GetDirectoryName(sourceFileMapping))) { Directory.Delete(Path.GetDirectoryName(sourceFileMapping), true); } } } } }
public void CoreDumpVerifyActions(ITestSettings settings) { this.TestPurpose("This test checks to see the behavior when do actions during core dump debugging."); this.WriteSettings(settings); this.Comment("Compile the application"); CompileApp(this, settings, DebuggeeMonikers.CoreDump.Action); this.Comment("Set initial debuggee for application"); IDebuggee debuggee = OpenDebuggee(this, settings, DebuggeeMonikers.CoreDump.Action); this.Comment("Launch the application to hit an exception and generate core dump"); string coreDumpPath = GenerateCoreDump(settings, DebuggeeMonikers.CoreDump.Action, debuggee); using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) { this.Comment("Configure the core dump before start debugging"); runner.LaunchCoreDump(settings.DebuggerSettings, debuggee, coreDumpPath); this.Comment("Start debugging to hit the exception and verify it should stop at correct source file and line"); runner.Expects.StoppedEvent(StoppedReason.Exception, srcClassName, 8).AfterConfigurationDone(); this.Comment("Verify the error message for relevant actions during core dump debugging"); using (IThreadInspector threadInspector = runner.GetThreadInspector()) { this.Comment("Get current frame object"); IFrameInspector currentFrame = threadInspector.Stack.First(); this.Comment("Verify current frame when stop at the exception"); threadInspector.AssertStackFrameNames(true, "myException::RaisedUnhandledException.*"); this.Comment("Try to evaluate a expression and verify the results"); string varEvalResult = currentFrame.Evaluate("result + 1"); Assert.Equal("11", varEvalResult); this.Comment("Try to evaluate a function and verify the error message"); EvaluateResponseValue evalResponse = runner.RunCommand(new EvaluateCommand("EvalFunc(100, 100)", currentFrame.Id)); // TODO: From VSCode IDE with the latest cpptools, the error message after evaluate function is "not availabe", but evalResponse.message is null, is it expected ? // Currently just simply verify the result is empty as a workaround, need to revisit this once get more information from logged bug #242418 this.Comment(string.Format(CultureInfo.InvariantCulture, "Actual evaluated result: {0}", evalResponse.body.result)); Assert.True(evalResponse.body.result.Equals(string.Empty)); this.Comment(string.Format(CultureInfo.InvariantCulture, "Actual evaluated respone message: {0}", evalResponse.message)); //Assert.True(evalResponse.message.Contains(evalError)); } this.Comment("Try to step in and verify the error message"); StepInCommand stepInCommand = new StepInCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepInCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepInCommand.Message)); Assert.Contains(stepInCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step in")); this.Comment("Try to step over and verify the error message"); StepOverCommand stepOverCommand = new StepOverCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepOverCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepOverCommand.Message)); Assert.Contains(stepOverCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step next")); this.Comment("Try to step out and verify the error message"); StepOutCommand stepOutCommand = new StepOutCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepOutCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepOutCommand.Message)); Assert.Contains(stepOutCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step out")); this.Comment("Try to continue and verify the error message"); ContinueCommand continueCommand = new ContinueCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(continueCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", continueCommand.Message)); Assert.Contains(continueCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "continue")); this.Comment("Try to set a breakpoint and verify the error message"); SourceBreakpoints bp = debuggee.Breakpoints(srcAppName, 16); SetBreakpointsResponseValue setBpResponse = runner.SetBreakpoints(bp); Assert.False(setBpResponse.body.breakpoints[0].verified); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", setBpResponse.body.breakpoints[0].message)); Assert.Contains(setBpResponse.body.breakpoints[0].message, bpError); this.Comment("Stop core dump debugging"); runner.DisconnectAndVerify(); } }