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 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 CompileKitchenSinkForExecution(ITestSettings settings) { this.TestPurpose("Compiles the kitchen sink debuggee for execution tests."); this.WriteSettings(settings); IDebuggee debuggee = SinkHelper.OpenAndCompile(this, settings.CompilerSettings, DebuggeeMonikers.KitchenSink.Execution); }
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 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(); } }