示例#1
0
        private void TestExitCode(PythonDebugger debugger, string filename, int expectedExitCode)
        {
            var process = DebugProcess(debugger, filename);

            bool created = false, exited = false;

            process.ThreadCreated += (sender, args) => {
                created = true;
            };
            process.ThreadExited += (sender, args) => {
                exited = true;
            };
            process.ProcessExited += (sender, args) => {
                Assert.AreEqual(args.ExitCode, expectedExitCode);
            };
            process.ExceptionRaised += (sender, args) => {
                process.Resume();
            };

            process.Start();
            process.WaitForExit();

            Assert.IsTrue(created);
            Assert.IsTrue(exited);
        }
示例#2
0
        private void TestModuleLoad(PythonDebugger debugger, string filename, params string[] expectedModulesLoaded)
        {
            var process = DebugProcess(debugger, filename);

            List <string> receivedFilenames = new List <string>();

            process.ModuleLoaded += (sender, args) => {
                receivedFilenames.Add(args.Module.Filename);
            };
            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();
            process.WaitForExit();

            Assert.IsTrue(receivedFilenames.Count >= expectedModulesLoaded.Length);
            var set = new HashSet <string>();

            foreach (var received in receivedFilenames)
            {
                set.Add(Path.GetFileName(received));
            }

            foreach (var file in expectedModulesLoaded)
            {
                Assert.IsTrue(set.Contains(file));
            }
        }
示例#3
0
        public void TestBreakpointFailed()
        {
            var debugger = new PythonDebugger();

            PythonThread     thread     = null;
            PythonBreakpoint breakPoint = null;
            var process = DebugProcess(debugger, DebuggerTestPath + "BreakpointTest.py", (newproc, newthread) => {
                breakPoint = newproc.AddBreakPoint("doesnotexist.py", 1);
                breakPoint.Add();
                thread = newthread;
            });

            bool bindFailed = false;

            process.BreakpointBindFailed += (sender, args) => {
                bindFailed = true;
                Assert.AreEqual(args.Breakpoint, breakPoint);
            };
            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();

            process.WaitForExit();

            Assert.AreEqual(bindFailed, true);
        }
示例#4
0
        internal static PythonProcess DebugProcess(this PythonDebugger debugger, PythonVersion version, string filename, Func <PythonProcess, PythonThread, Task> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string arguments = "")
        {
            string fullPath = Path.GetFullPath(filename);
            string dir      = cwd ?? Path.GetFullPath(Path.GetDirectoryName(filename));

            if (!String.IsNullOrEmpty(arguments))
            {
                arguments = "\"" + fullPath + "\" " + arguments;
            }
            else
            {
                arguments = "\"" + fullPath + "\"";
            }
            var process = debugger.CreateProcess(version.Version, version.InterpreterPath, arguments, dir, "", interpreterOptions, debugOptions);

            process.DebuggerOutput += (sender, args) => {
                Console.WriteLine("{0}: {1}", args.Thread?.Id, args.Output);
            };
            process.ProcessLoaded += async(sender, args) => {
                if (onLoaded != null)
                {
                    await onLoaded(process, args.Thread);
                }
                if (resumeOnProcessLoaded)
                {
                    await process.ResumeAsync(default(CancellationToken));
                }
            };

            return(process);
        }
示例#5
0
        private async Task AttachAsync(string filename, int lineNo)
        {
            var           debugger = new PythonDebugger();
            PythonProcess process  = debugger.DebugProcess(Version, DebuggerTestPath + filename, null, async(newproc, newthread) => {
                var breakPoint = newproc.AddBreakpointByFileExtension(lineNo, filename);
                await breakPoint.AddAsync(TimeoutToken());
            });

            _processes.Add(process);

            long?threadAtBreakpoint = null;

            using (var brkHit = new AutoResetEvent(false))
                using (var procExited = new AutoResetEvent(false)) {
                    EventHandler <BreakpointHitEventArgs> breakpointHitHandler = (s, e) => {
                        threadAtBreakpoint = e.Thread.Id;
                        SafeSetEvent(brkHit);
                    };
                    EventHandler <ProcessExitedEventArgs> processExitedHandler = (s, e) => SafeSetEvent(procExited);
                    process.BreakpointHit += breakpointHitHandler;
                    process.ProcessExited += processExitedHandler;

                    try {
                        await process.StartAsync();
                    } catch (Win32Exception ex) {
                        _processes.Remove(process);
                        if (ex.HResult == -2147467259 /*0x80004005*/)
                        {
                            Assert.Inconclusive("Required Python interpreter is not installed");
                        }
                        else
                        {
                            Assert.Fail("Process start failed:\r\n" + ex.ToString());
                        }
                    }

                    var handles = new[] { brkHit, procExited };
                    if (WaitHandle.WaitAny(handles, 25000) != 0)
                    {
                        Assert.Fail("Failed to wait on event");
                    }

                    process.BreakpointHit -= breakpointHitHandler;
                    process.ProcessExited -= processExitedHandler;
                }

            await _evaluator.AttachProcessAsync(process, new MockThreadIdMapper());

            // AttachProcessAsync calls InitializeAsync which sets the active
            // thread by using the DTE (which is null in these tests), so we
            // adjust it to the correct thread where breakpoint was hit.
            if (threadAtBreakpoint != null)
            {
                _evaluator.ChangeActiveThread(threadAtBreakpoint.Value, false);
            }
        }
示例#6
0
        public void TestModuleLoad()
        {
            var debugger = new PythonDebugger();

            // main file is reported
            TestModuleLoad(debugger, @"Python.VS.TestData\HelloWorld\Program.py", "Program.py");

            // imports are reported
            TestModuleLoad(debugger, DebuggerTestPath + @"imports_other.py", "imports_other.py", "is_imported.py");
        }
示例#7
0
        private void EvalTest(string filename, int lineNo, string frameName, int frameIndex, EvalResult eval)
        {
            var          debugger = new PythonDebugger();
            PythonThread thread   = null;
            var          process  = DebugProcess(debugger, DebuggerTestPath + filename, (newproc, newthread) => {
                var breakPoint = newproc.AddBreakPoint(filename, lineNo);
                breakPoint.Add();
                thread = newthread;
            });

            AutoResetEvent brkHit = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) => {
                brkHit.Set();
            };
            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();

            brkHit.WaitOne();

            var frames = thread.GetFrames();

            PythonEvaluationResult obj = null;
            string errorMsg;

            if (eval.IsError)
            {
                Assert.IsTrue(!frames[frameIndex].TryParseText(eval.Expression, out errorMsg));
                Assert.AreEqual(errorMsg, eval.ExceptionText);
            }
            else
            {
                Assert.IsTrue(frames[frameIndex].TryParseText(eval.Expression, out errorMsg));
                Assert.AreEqual(errorMsg, null);

                AutoResetEvent textExecuted = new AutoResetEvent(false);
                Assert.AreEqual(frameName, frames[frameIndex].FunctionName);
                frames[frameIndex].ExecuteText(eval.Expression, (completion) => {
                    obj = completion;
                    textExecuted.Set();
                }
                                               );
                textExecuted.WaitOne();
                eval.Validate(obj);
            }

            process.Continue();

            process.WaitForExit();
        }
示例#8
0
        public void TestStartup()
        {
            var debugger = new PythonDebugger();

            // hello world
            TestExitCode(debugger, @"Python.VS.TestData\HelloWorld\Program.py", 0);

            // test which calls sys.exit(23)
            TestExitCode(debugger, DebuggerTestPath + @"SysExit.py", 23);

            // test which calls raise Exception()
            TestExitCode(debugger, DebuggerTestPath + @"ExceptionalExit.py", 1);
        }
示例#9
0
        private PythonProcess DebugProcess(PythonDebugger debugger, string filename, Action <PythonProcess, PythonThread> onLoaded = null)
        {
            string fullPath = Path.GetFullPath(filename);
            string dir      = Path.GetFullPath(Path.GetDirectoryName(filename));
            var    process  = debugger.CreateProcess(Version.Version, Version.Path, "\"" + fullPath + "\"", dir, "");

            process.ProcessLoaded += (sender, args) => {
                if (onLoaded != null)
                {
                    onLoaded(process, args.Thread);
                }
                process.Resume();
            };

            return(process);
        }
示例#10
0
        private void Attach(string filename, int lineNo)
        {
            var           debugger = new PythonDebugger();
            PythonProcess process  = debugger.DebugProcess(Version, DebuggerTestPath + filename, (newproc, newthread) => {
                var breakPoint = newproc.AddBreakPointByFileExtension(lineNo, filename);
                breakPoint.Add();
                _evaluator.AttachProcess(newproc, new MockThreadIdMapper());
            },
                                                           debugOptions: PythonDebugOptions.CreateNoWindow);

            _processes.Add(process);

            using (var brkHit = new AutoResetEvent(false))
                using (var procExited = new AutoResetEvent(false)) {
                    EventHandler <BreakpointHitEventArgs> breakpointHitHandler = (s, e) => brkHit.Set();
                    EventHandler <ProcessExitedEventArgs> processExitedHandler = (s, e) => procExited.Set();
                    process.BreakpointHit += breakpointHitHandler;
                    process.ProcessExited += processExitedHandler;

                    try {
                        process.Start();
                    } catch (Win32Exception ex) {
                        _processes.Remove(process);
#if DEV11_OR_LATER
                        if (ex.HResult == -2147467259 /*0x80004005*/)
                        {
                            Assert.Inconclusive("Required Python interpreter is not installed");
                        }
                        else
#endif
                        {
                            Assert.Fail("Process start failed:\r\n" + ex.ToString());
                        }
                    }

                    var handles = new[] { brkHit, procExited };
                    if (WaitHandle.WaitAny(handles, 25000) != 0)
                    {
                        Assert.Fail("Failed to wait on event");
                    }

                    process.BreakpointHit -= breakpointHitHandler;
                    process.ProcessExited -= processExitedHandler;
                }

            _evaluator.AttachProcess(process, new MockThreadIdMapper());
        }
示例#11
0
        public void TestBreakAllThreads()
        {
            var debugger = new PythonDebugger();

            PythonThread   thread  = null;
            AutoResetEvent loaded  = new AutoResetEvent(false);
            var            process = DebugProcess(debugger, DebuggerTestPath + "InfiniteThreads.py", (newproc, newthread) => {
                loaded.Set();
                thread = newthread;
            });

            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();
            if (!loaded.WaitOne(10000))
            {
                Assert.Fail("Failed to load");
            }

            AutoResetEvent breakComplete = new AutoResetEvent(false);

            process.AsyncBreakComplete += (sender, args) => {
                breakComplete.Set();
            };

            // let loop run
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(50);

                Debug.WriteLine(String.Format("Breaking {0}", i));
                process.Break();
                if (!breakComplete.WaitOne(10000))
                {
                    Console.WriteLine("Failed to break");
                }
                process.Resume();
                Debug.WriteLine(String.Format("Resumed {0}", i));
            }

            process.Terminate();
        }
示例#12
0
        internal async Task <PythonThread> RunAndBreakAsync(string filename, int lineNo, string breakFilename = null, string arguments = "", Action processLoaded = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput)
        {
            PythonThread thread;

            var debugger = new PythonDebugger();

            thread = null;
            PythonProcess process = DebugProcess(debugger, DebuggerTestPath + filename, async(newproc, newthread) =>
            {
                var breakPoint = newproc.AddBreakpointByFileExtension(lineNo, breakFilename ?? filename);
                await breakPoint.AddAsync(TimeoutToken());
                thread = newthread;
                processLoaded?.Invoke();
            },
                                                 arguments: arguments,
                                                 debugOptions: debugOptions);

            AutoResetEvent brkHit = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) =>
            {
                thread = args.Thread;
                brkHit.Set();
            };

            bool ready = false;

            try
            {
                await process.StartAsync();

                AssertWaited(brkHit);
                ready = true;
            }
            finally
            {
                if (!ready)
                {
                    process.Terminate();
                }
            }

            return(thread);
        }
示例#13
0
        private void TestException(PythonDebugger debugger, string filename, bool resumeProcess, params ExceptionInfo[] exceptions)
        {
            var  process = DebugProcess(debugger, filename);
            bool loaded  = false;

            process.ProcessLoaded += (sender, args) => {
                loaded = true;
            };
            int curException = 0;

            process.ExceptionRaised += (sender, args) => {
                // V30 raises an exception as the process shuts down.
                if (loaded && ((Version.Version == PythonLanguageVersion.V30 && curException < exceptions.Length) || Version.Version != PythonLanguageVersion.V30))
                {
                    Assert.AreEqual(args.Exception.TypeName, exceptions[curException].TypeName);

                    // http://ironpython.codeplex.com/workitem/30130
                    if (GetType() != typeof(DebuggerTestsIpy))
                    {
                        Assert.IsTrue(args.Exception.Description.IndexOf("line " + exceptions[curException].LineNumber) != -1);
                    }
                    Assert.IsTrue(args.Exception.Description.IndexOf(filename) != -1);

                    curException++;
                    if (resumeProcess)
                    {
                        process.Resume();
                    }
                    else
                    {
                        args.Thread.Resume();
                    }
                }
                else
                {
                    args.Thread.Resume();
                }
            };

            process.Start();
            process.WaitForExit();

            Assert.AreEqual(exceptions.Length, curException);
        }
示例#14
0
        public void TestBreakAll()
        {
            var debugger = new PythonDebugger();

            PythonThread   thread  = null;
            AutoResetEvent loaded  = new AutoResetEvent(false);
            var            process = DebugProcess(debugger, DebuggerTestPath + "BreakAllTest.py", (newproc, newthread) => {
                loaded.Set();
                thread = newthread;
            });

            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();
            if (!loaded.WaitOne(10000))
            {
                Assert.Fail("Failed to load");
            }

            // let loop run
            Thread.Sleep(500);
            AutoResetEvent breakComplete = new AutoResetEvent(false);
            PythonThread   breakThread   = null;

            process.AsyncBreakComplete += (sender, args) => {
                breakThread = args.Thread;
                breakComplete.Set();
            };

            process.Break();
            if (!breakComplete.WaitOne(10000))
            {
                Assert.Fail("failed to break");
            }

            Assert.AreEqual(breakThread, thread);

            process.Resume();

            process.Terminate();
        }
示例#15
0
        private void LocalsTest(string filename, int lineNo, string[] paramNames, string[] localsNames)
        {
            var          debugger = new PythonDebugger();
            PythonThread thread   = null;
            var          process  = DebugProcess(debugger, DebuggerTestPath + filename, (newproc, newthread) => {
                var breakPoint = newproc.AddBreakPoint(filename, lineNo);
                breakPoint.Add();
                thread = newthread;
            });

            AutoResetEvent brkHit = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) => {
                brkHit.Set();
            };
            process.ExceptionRaised += (sender, args) => {
                // some versions of Python raise exceptions
                args.Thread.Resume();
            };

            process.Start();

            brkHit.WaitOne();

            var frames         = thread.GetFrames();
            var localsExpected = new HashSet <string>(localsNames);
            var paramsExpected = new HashSet <string>(paramNames);

            Assert.IsTrue(localsExpected.ContainsExactly(frames[0].Locals.Select(x => x.Expression)));
            Assert.IsTrue(paramsExpected.ContainsExactly(frames[0].Parameters.Select(x => x.Expression)));
            Assert.AreEqual(frames[0].FileName, Path.GetFullPath(DebuggerTestPath + filename));

            process.Continue();

            process.WaitForExit();
        }
示例#16
0
        public void TestExceptions()
        {
            var debugger = new PythonDebugger();

            for (int i = 0; i < 2; i++)
            {
                TestException(debugger, DebuggerTestPath + @"SimpleException.py", i == 0, new ExceptionInfo(ExceptionModule + ".Exception", 3));

                TestException(debugger, DebuggerTestPath + ComplexExceptions, i == 0,
                              new ExceptionInfo(PickleModule + ".PickleError", 6),
                              new ExceptionInfo(ExceptionModule + ".StopIteration", 13),
                              new ExceptionInfo(ExceptionModule + ".NameError", 15),
                              new ExceptionInfo(ExceptionModule + ".StopIteration", 21),
                              new ExceptionInfo(ExceptionModule + ".NameError", 23),
                              new ExceptionInfo(ExceptionModule + ".Exception", 29),
                              new ExceptionInfo(ExceptionModule + ".Exception", 32)
                              );

                if (Version.Version.Is2x())
                {
                    TestException(debugger, DebuggerTestPath + @"UnicodeException.py", i == 0, new ExceptionInfo(ExceptionModule + ".Exception", 3));
                }
            }
        }
示例#17
0
        /// <summary>
        /// Runs the given file name setting break points at linenos.  Expects to hit the lines
        /// in lineHits as break points in the order provided in lineHits.  If lineHits is negative
        /// expects to hit the positive number and then removes the break point.
        /// </summary>
        private void BreakpointTest(string filename, int[] linenos, int[] lineHits, string[] conditions = null, bool[] breakWhenChanged = null)
        {
            var          debugger = new PythonDebugger();
            PythonThread thread   = null;
            var          process  = DebugProcess(debugger, DebuggerTestPath + filename, (newproc, newthread) => {
                for (int i = 0; i < linenos.Length; i++)
                {
                    var line = linenos[i];

                    int finalLine = line;
                    if (finalLine < 0)
                    {
                        finalLine = -finalLine;
                    }

                    PythonBreakpoint breakPoint;
                    if (conditions != null)
                    {
                        if (breakWhenChanged != null)
                        {
                            breakPoint = newproc.AddBreakPoint(filename, line, conditions[i], breakWhenChanged[i]);
                        }
                        else
                        {
                            breakPoint = newproc.AddBreakPoint(filename, line, conditions[i]);
                        }
                    }
                    else
                    {
                        breakPoint = newproc.AddBreakPoint(filename, line);
                    }

                    breakPoint.Add();
                }
                thread = newthread;
            });

            process.BreakpointBindFailed += (sender, args) => {
                Assert.Fail("unexpected bind failure");
            };

            var lineList = new List <int>(linenos);

            int breakpointBound = 0;
            int breakpointHit   = 0;

            process.BreakpointBindSucceeded += (sender, args) => {
                Assert.AreEqual(args.Breakpoint.Filename, filename);
                int index = lineList.IndexOf(args.Breakpoint.LineNo);
                Assert.IsTrue(index != -1);
                lineList[index] = -1;
                breakpointBound++;
            };

            process.BreakpointHit += (sender, args) => {
                if (lineHits[breakpointHit] < 0)
                {
                    Assert.AreEqual(args.Breakpoint.LineNo, -lineHits[breakpointHit++]);
                    try {
                        args.Breakpoint.Remove();
                    } catch {
                        Debug.Assert(false);
                    }
                }
                else
                {
                    Assert.AreEqual(args.Breakpoint.LineNo, lineHits[breakpointHit++]);
                }
                Assert.AreEqual(args.Thread, thread);
                process.Continue();
            };

            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();

            process.WaitForExit();

            Assert.AreEqual(breakpointHit, lineHits.Length);
            Assert.AreEqual(breakpointBound, linenos.Length);
        }
示例#18
0
        public void SetNextLineTest()
        {
            if (GetType() == typeof(DebuggerTestsIpy))
            {
                //http://ironpython.codeplex.com/workitem/30129
                return;
            }

            var          debugger = new PythonDebugger();
            PythonThread thread   = null;
            var          process  = DebugProcess(debugger, DebuggerTestPath + @"SetNextLine.py", (newproc, newthread) => {
                var breakPoint = newproc.AddBreakPoint("SetNextLine.py", 1);
                breakPoint.Add();
                thread = newthread;
            });

            AutoResetEvent brkHit   = new AutoResetEvent(false);
            AutoResetEvent stepDone = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) => {
                brkHit.Set();
            };
            process.StepComplete += (sender, args) => {
                stepDone.Set();
            };
            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();

            brkHit.WaitOne();

            var moduleFrame = thread.GetFrames()[0];

            Assert.AreEqual(moduleFrame.StartLine, 1);
            if (GetType() != typeof(DebuggerTestsIpy))
            {
                Assert.AreEqual(moduleFrame.EndLine, 13);
            }

            // skip over def f()
            Assert.IsTrue(moduleFrame.SetLineNumber(6));

            // set break point in g, run until we hit it.
            var newBp = process.AddBreakPoint("SetNextLine.py", 7);

            newBp.Add();

            process.Resume();
            brkHit.WaitOne();

            thread.StepOver(); // step over x = 42
            stepDone.WaitOne();

            // skip y = 100
            Assert.IsTrue(moduleFrame.SetLineNumber(9));

            thread.StepOver(); // step over z = 200
            stepDone.WaitOne();

            // z shouldn't be defined
            var frames = thread.GetFrames();

            new HashSet <string>(new[] { "x", "z" }).ContainsExactly(frames[0].Locals.Select(x => x.Expression));

            // set break point in module, run until we hit it.
            newBp = process.AddBreakPoint("SetNextLine.py", 13);
            newBp.Add();
            thread.Resume();
            brkHit.WaitOne();

            // f shouldn't be defined.
            frames = thread.GetFrames();
            new HashSet <string>(new[] { "sys", "g" }).ContainsExactly(frames[0].Locals.Select(x => x.Expression));

            process.Continue();

            process.WaitForExit();
        }
示例#19
0
        internal async Task StepTestAsync(string filename, string breakFile, string arguments, int[] breakLines, Action <PythonProcess>[] breakAction, Action processLoaded, PythonDebugOptions options = PythonDebugOptions.RedirectOutput, bool waitForExit = true, params ExpectedStep[] kinds)
        {
            Console.WriteLine("--- Begin Step Test ---");
            var debugger = new PythonDebugger();

            if (breakFile == null)
            {
                breakFile = filename;
            }

            string fullPath = Path.GetFullPath(filename);
            string dir      = Path.GetDirectoryName(filename);
            var    process  = debugger.CreateProcess(Version.Version, Version.InterpreterPath, "\"" + fullPath + "\" " + (arguments ?? ""), dir, "", null, options, DebugLog);

            try {
                PythonThread thread = null;
                process.ThreadCreated += (sender, args) => {
                    thread = args.Thread;
                };


                AutoResetEvent processEvent = new AutoResetEvent(false);

                bool processLoad = false, stepComplete = false;
                process.ProcessLoaded += async(sender, args) => {
                    foreach (var breakLine in breakLines)
                    {
                        var bp = process.AddBreakpointByFileExtension(breakLine, breakFile);
                        await bp.AddAsync(TimeoutToken());
                    }

                    processLoad = true;
                    processEvent.Set();
                    processLoaded?.Invoke();
                };

                process.StepComplete += (sender, args) => {
                    stepComplete = true;
                    processEvent.Set();
                };

                int breakHits             = 0;
                ExceptionDispatchInfo edi = null;
                process.BreakpointHit += (sender, args) => {
                    try {
                        Console.WriteLine("Breakpoint hit");
                        if (breakAction != null)
                        {
                            if (breakHits >= breakAction.Length)
                            {
                                Assert.Fail("Unexpected breakpoint hit at {0}:{1}", args.Breakpoint.Filename, args.Breakpoint.LineNo);
                            }
                            breakAction[breakHits++](process);
                        }
                        stepComplete = true;
                        processEvent.Set();
                    } catch (Exception ex) {
                        edi = ExceptionDispatchInfo.Capture(ex);
                        try {
                            processEvent.Set();
                        } catch { }
                    }
                };

                await process.StartAsync();

                for (int curStep = 0; curStep < kinds.Length; curStep++)
                {
                    Console.WriteLine("Step {0} {1}", curStep, kinds[curStep].Kind);
                    // process the stepping events as they occur, we cannot callback during the
                    // event because the notificaiton happens on the debugger thread and we
                    // need to callback to get the frames.
                    AssertWaited(processEvent);
                    edi?.Throw();

                    // first time through we hit process load, each additional time we should hit step complete.
                    Debug.Assert((processLoad == true && stepComplete == false && curStep == 0) ||
                                 (stepComplete == true && processLoad == false && curStep != 0));

                    processLoad = stepComplete = false;

                    var frames   = thread.Frames;
                    var stepInfo = kinds[curStep];
                    Assert.AreEqual(stepInfo.StartLine, frames[0].LineNo, String.Format("{0} != {1} on {2} step", stepInfo.StartLine, frames[0].LineNo, curStep));

                    switch (stepInfo.Kind)
                    {
                    case StepKind.Into:
                        await thread.StepIntoAsync(TimeoutToken());

                        break;

                    case StepKind.Out:
                        await thread.StepOutAsync(TimeoutToken());

                        break;

                    case StepKind.Over:
                        await thread.StepOverAsync(TimeoutToken());

                        break;

                    case StepKind.Resume:
                        await process.ResumeAsync(TimeoutToken());

                        break;
                    }
                }
                if (waitForExit)
                {
                    WaitForExit(process);
                }
            } finally {
                process.Terminate();
            }
        }
示例#20
0
            public async Task RunAsync()
            {
                string runFileName = RunFileName;

                if (!Path.IsPathRooted(runFileName))
                {
                    runFileName = _tests.DebuggerTestPath + runFileName;
                }

                string breakFileName = BreakFileName;

                if (breakFileName != null && !Path.IsPathRooted(breakFileName))
                {
                    breakFileName = _tests.DebuggerTestPath + breakFileName;
                }

                foreach (var bp in Breakpoints)
                {
                    var fileName = bp.FileName ?? breakFileName ?? runFileName;
                    if (fileName.EndsWith(".py"))
                    {
                        Assert.IsTrue(bp is Breakpoint);
                    }
                    else
                    {
                        Assert.IsTrue(bp is DjangoBreakpoint);
                    }
                }

                var bps                  = new Dictionary <PythonBreakpoint, BreakpointBase>();
                var unboundBps           = new HashSet <Breakpoint>();
                var breakpointsToBeBound = Breakpoints.Count;

                var          debugger = new PythonDebugger();
                PythonThread thread   = null;

                // Used to signal exceptions from debugger event handlers that run on a background thread.
                var backgroundException = new TaskCompletionSource <bool>();

                var processLoaded = new TaskCompletionSource <bool>();
                var process       = _tests.DebugProcess(
                    debugger,
                    runFileName,
                    cwd: WorkingDirectory,
                    arguments: Arguments,
                    resumeOnProcessLoaded: false,
                    onLoaded: async(newproc, newthread) => {
                    try {
                        foreach (var bp in Breakpoints)
                        {
                            var fileName = bp.FileName ?? breakFileName ?? runFileName;

                            PythonBreakpoint breakpoint;
                            var pyBP = bp as Breakpoint;
                            if (pyBP != null)
                            {
                                breakpoint = newproc.AddBreakpoint(fileName, pyBP.LineNumber, pyBP.ConditionKind, pyBP.Condition, pyBP.PassCountKind, pyBP.PassCount);
                                unboundBps.Add(pyBP);
                            }
                            else
                            {
                                var djangoBP = bp as DjangoBreakpoint;
                                if (djangoBP != null)
                                {
                                    breakpoint = newproc.AddDjangoBreakpoint(fileName, djangoBP.LineNumber);
                                    // Django breakpoints are never bound.
                                    --breakpointsToBeBound;
                                }
                                else
                                {
                                    Assert.Fail("Unknown breakpoint type.");
                                    return;
                                }
                            }

                            // Bind failed and succeeded events expect to find the breakpoint
                            // in the dictionary, so update it before sending the add request.
                            bps.Add(breakpoint, bp);
                            await breakpoint.AddAsync(TimeoutToken());
                        }

                        OnProcessLoaded?.Invoke(newproc);

                        thread = newthread;
                        processLoaded.SetResult(true);
                    } catch (Exception ex) {
                        backgroundException.TrySetException(ex);
                    }
                },
                    interpreterOptions: InterpreterOptions
                    );

                int breakpointsBound    = 0;
                int breakpointsNotBound = 0;
                int nextExpectedHit     = 0;

                var allBreakpointsHit        = new TaskCompletionSource <bool>();
                var allBreakpointBindResults = new TaskCompletionSource <bool>();

                if (breakpointsToBeBound == 0)
                {
                    allBreakpointBindResults.SetResult(true);
                }

                try {
                    process.BreakpointBindFailed += (sender, args) => {
                        try {
                            var bp = (Breakpoint)bps[args.Breakpoint];
                            if (bp != null && !(bp.IsBindFailureExpected ?? IsBindFailureExpected))
                            {
                                Assert.Fail("Breakpoint at {0}:{1} failed to bind.", bp.FileName ?? breakFileName ?? runFileName, bp.LineNumber);
                            }
                            ++breakpointsNotBound;
                            if (breakpointsBound + breakpointsNotBound == breakpointsToBeBound)
                            {
                                allBreakpointBindResults.SetResult(true);
                            }
                        } catch (Exception ex) {
                            backgroundException.TrySetException(ex);
                        }
                    };

                    process.BreakpointBindSucceeded += (sender, args) => {
                        try {
                            var bp = (Breakpoint)bps[args.Breakpoint];
                            Assert.AreEqual(bp.FileName ?? breakFileName ?? runFileName, args.Breakpoint.Filename);
                            Assert.IsTrue(unboundBps.Remove(bp));
                            ++breakpointsBound;
                            if (breakpointsBound + breakpointsNotBound == breakpointsToBeBound)
                            {
                                allBreakpointBindResults.SetResult(true);
                            }
                        } catch (Exception ex) {
                            backgroundException.TrySetException(ex);
                        }
                    };

                    process.BreakpointHit += async(sender, args) => {
                        try {
                            if (nextExpectedHit < ExpectedHits.Count)
                            {
                                var bp = Breakpoints[ExpectedHits[nextExpectedHit]];
                                Trace.TraceInformation("Hit {0}:{1}", args.Breakpoint.Filename, args.Breakpoint.LineNo);
                                Assert.AreSame(bp, bps[args.Breakpoint]);

                                if (bp.RemoveWhenHit)
                                {
                                    await args.Breakpoint.RemoveAsync(TimeoutToken());
                                }

                                if (bp.ExpectHitOnMainThread ?? ExpectHitOnMainThread)
                                {
                                    Assert.AreSame(thread, args.Thread);
                                }

                                bp.OnHit?.Invoke(args);

                                if (++nextExpectedHit == ExpectedHits.Count)
                                {
                                    allBreakpointsHit.SetResult(true);
                                }
                            }

                            try {
                                await process.ResumeAsync(TimeoutToken());
                            } catch (TaskCanceledException) {
                                // If we don't wait for exit, the Terminate() call
                                // will cause ResumeAsync to be canceled.
                                if (WaitForExit)
                                {
                                    throw;
                                }
                            }
                        } catch (Exception ex) {
                            backgroundException.TrySetException(ex);
                        }
                    };

                    await process.StartAsync();

                    Assert.IsTrue(WaitForAny(10000, processLoaded.Task, backgroundException.Task), "Timed out waiting for process load");

                    await process.AutoResumeThread(thread.Id, TimeoutToken());

                    if (breakpointsToBeBound > 0)
                    {
                        Assert.IsTrue(WaitForAny(10000, allBreakpointBindResults.Task, backgroundException.Task), "Timed out waiting for breakpoints to bind");
                    }
                } finally {
                    if (WaitForExit)
                    {
                        _tests.WaitForExit(process);
                    }
                    else
                    {
                        Assert.IsTrue(WaitForAny(20000, allBreakpointsHit.Task, backgroundException.Task), "Timed out waiting for breakpoints to hit");
                        process.Terminate();
                    }
                }

                if (backgroundException.Task.IsFaulted)
                {
                    backgroundException.Task.GetAwaiter().GetResult();
                }

                Assert.AreEqual(ExpectedHits.Count, nextExpectedHit);
                Assert.IsTrue(unboundBps.All(bp => bp.IsBindFailureExpected ?? IsBindFailureExpected));
            }
示例#21
0
 internal PythonProcess DebugProcess(PythonDebugger debugger, string filename, Func <PythonProcess, PythonThread, Task> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string arguments = "")
 {
     return(debugger.DebugProcess(Version, filename, DebugLog, onLoaded, resumeOnProcessLoaded, interpreterOptions, debugOptions, cwd, arguments));
 }
示例#22
0
 internal object DebugProcess(PythonDebugger debugger, string runFileName, string cwd, string arguments, bool resumeOnProcessLoaded, object onLoaded, string interpreterOptions)
 {
     throw new NotImplementedException();
 }
示例#23
0
            public void Run()
            {
                string runFileName = RunFileName;

                if (!Path.IsPathRooted(runFileName))
                {
                    runFileName = _tests.DebuggerTestPath + runFileName;
                }

                string breakFileName = BreakFileName;

                if (breakFileName != null && !Path.IsPathRooted(breakFileName))
                {
                    breakFileName = _tests.DebuggerTestPath + breakFileName;
                }

                foreach (var bp in Breakpoints)
                {
                    var fileName = bp.FileName ?? breakFileName ?? runFileName;
                    if (fileName.EndsWith(".py"))
                    {
                        Assert.IsTrue(bp is Breakpoint);
                    }
                    else
                    {
                        Assert.IsTrue(bp is DjangoBreakpoint);
                    }
                }

                var bps                  = new Dictionary <PythonBreakpoint, BreakpointBase>();
                var unboundBps           = new HashSet <Breakpoint>();
                var breakpointsToBeBound = Breakpoints.Count;

                var          debugger = new PythonDebugger();
                PythonThread thread   = null;

                // Used to signal exceptions from debugger event handlers that run on a background thread.
                var backgroundException = new TaskCompletionSource <bool>();

                var processLoaded = new TaskCompletionSource <bool>();
                var process       = _tests.DebugProcess(
                    debugger,
                    runFileName,
                    cwd: WorkingDirectory,
                    arguments: Arguments,
                    resumeOnProcessLoaded: false,
                    onLoaded: (newproc, newthread) => {
                    try {
                        foreach (var bp in Breakpoints)
                        {
                            var fileName = bp.FileName ?? breakFileName ?? runFileName;

                            PythonBreakpoint breakpoint;
                            var pyBP = bp as Breakpoint;
                            if (pyBP != null)
                            {
                                breakpoint = newproc.AddBreakPoint(fileName, pyBP.LineNumber, pyBP.ConditionKind, pyBP.Condition, pyBP.PassCountKind, pyBP.PassCount);
                                unboundBps.Add(pyBP);
                            }
                            else
                            {
                                var djangoBP = bp as DjangoBreakpoint;
                                if (djangoBP != null)
                                {
                                    breakpoint = newproc.AddDjangoBreakPoint(fileName, djangoBP.LineNumber);
                                    // Django breakpoints are never bound.
                                    --breakpointsToBeBound;
                                }
                                else
                                {
                                    Assert.Fail("Unknown breakpoint type.");
                                    return;
                                }
                            }

                            breakpoint.Add();
                            bps.Add(breakpoint, bp);
                        }

                        if (OnProcessLoaded != null)
                        {
                            OnProcessLoaded(newproc);
                        }

                        thread = newthread;
                        processLoaded.SetResult(true);
                    } catch (Exception ex) {
                        backgroundException.SetException(ex);
                    }
                },
                    interpreterOptions: InterpreterOptions
                    );

                int breakpointsBound    = 0;
                int breakpointsNotBound = 0;
                int nextExpectedHit     = 0;

                var allBreakpointsHit        = new TaskCompletionSource <bool>();
                var allBreakpointBindResults = new TaskCompletionSource <bool>();

                if (breakpointsToBeBound == 0)
                {
                    allBreakpointBindResults.SetResult(true);
                }

                try {
                    process.BreakpointBindFailed += (sender, args) => {
                        try {
                            var bp = (Breakpoint)bps[args.Breakpoint];
                            if (bp != null && !(bp.IsBindFailureExpected ?? IsBindFailureExpected))
                            {
                                Assert.Fail("Breakpoint at {0}:{1} failed to bind.", bp.FileName ?? breakFileName ?? runFileName, bp.LineNumber);
                            }
                            ++breakpointsNotBound;
                            if (breakpointsBound + breakpointsNotBound == breakpointsToBeBound)
                            {
                                allBreakpointBindResults.SetResult(true);
                            }
                        } catch (Exception ex) {
                            backgroundException.SetException(ex);
                        }
                    };

                    process.BreakpointBindSucceeded += (sender, args) => {
                        try {
                            var bp = (Breakpoint)bps[args.Breakpoint];
                            Assert.AreEqual(bp.FileName ?? breakFileName ?? runFileName, args.Breakpoint.Filename);
                            Assert.IsTrue(unboundBps.Remove(bp));
                            ++breakpointsBound;
                            if (breakpointsBound + breakpointsNotBound == breakpointsToBeBound)
                            {
                                allBreakpointBindResults.SetResult(true);
                            }
                        } catch (Exception ex) {
                            backgroundException.SetException(ex);
                        }
                    };

                    process.BreakpointHit += (sender, args) => {
                        try {
                            if (nextExpectedHit < ExpectedHits.Count)
                            {
                                var bp = Breakpoints[ExpectedHits[nextExpectedHit]];
                                Assert.AreSame(bp, bps[args.Breakpoint]);

                                if (bp.RemoveWhenHit)
                                {
                                    args.Breakpoint.Remove();
                                }

                                if (bp.ExpectHitOnMainThread ?? ExpectHitOnMainThread)
                                {
                                    Assert.AreSame(thread, args.Thread);
                                }

                                if (bp.OnHit != null)
                                {
                                    bp.OnHit(args);
                                }

                                if (++nextExpectedHit == ExpectedHits.Count)
                                {
                                    allBreakpointsHit.SetResult(true);
                                }
                            }
                            process.Continue();
                        } catch (Exception ex) {
                            backgroundException.SetException(ex);
                        }
                    };

                    process.Start();
                    WaitForAny(10000, processLoaded.Task, backgroundException.Task);

                    process.AutoResumeThread(thread.Id);
                    if (breakpointsToBeBound > 0)
                    {
                        WaitForAny(10000, allBreakpointBindResults.Task, backgroundException.Task);
                    }
                } finally {
                    if (WaitForExit)
                    {
                        _tests.WaitForExit(process);
                    }
                    else
                    {
                        WaitForAny(10000, allBreakpointsHit.Task, backgroundException.Task);
                        process.Terminate();
                    }
                }

                if (backgroundException.Task.IsFaulted)
                {
                    backgroundException.Task.GetAwaiter().GetResult();
                }

                Assert.AreEqual(ExpectedHits.Count, nextExpectedHit);
                Assert.IsTrue(unboundBps.All(bp => bp.IsBindFailureExpected ?? IsBindFailureExpected));
            }
示例#24
0
        private void ChildTest(string filename, int lineNo, string text, params ChildInfo[] children)
        {
            var          debugger = new PythonDebugger();
            PythonThread thread   = null;
            var          process  = DebugProcess(debugger, DebuggerTestPath + filename, (newproc, newthread) => {
                var breakPoint = newproc.AddBreakPoint(filename, lineNo);
                breakPoint.Add();
                thread = newthread;
            });

            AutoResetEvent brkHit = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) => {
                brkHit.Set();
            };
            process.ExceptionRaised += (sender, args) => {
                // some versions of Python raise exceptions during startup
                args.Thread.Resume();
            };

            process.Start();

            brkHit.WaitOne();

            var frames = thread.GetFrames();

            AutoResetEvent         evalComplete = new AutoResetEvent(false);
            PythonEvaluationResult evalRes      = null;

            frames[0].ExecuteText(text, (completion) => {
                evalRes = completion;
                evalComplete.Set();
            });

            evalComplete.WaitOne();
            Assert.IsTrue(evalRes != null);


            if (children == null)
            {
                Assert.IsTrue(!evalRes.IsExpandable);
                Assert.IsTrue(evalRes.GetChildren(Int32.MaxValue) == null);
            }
            else
            {
                Assert.IsTrue(evalRes.IsExpandable);
                var childrenReceived = new List <PythonEvaluationResult>(evalRes.GetChildren(Int32.MaxValue));

                Assert.IsTrue(children.Length == childrenReceived.Count);
                for (int i = 0; i < children.Length; i++)
                {
                    bool foundChild = false;
                    for (int j = 0; j < childrenReceived.Count; j++)
                    {
                        if (childrenReceived[j].ChildText == children[i].ChildText && childrenReceived[j].StringRepr == children[i].Repr)
                        {
                            foundChild = true;

                            if (children[i].ChildText.StartsWith("["))
                            {
                                Assert.AreEqual(childrenReceived[j].Expression, text + children[i].ChildText);
                            }
                            else
                            {
                                Assert.AreEqual(childrenReceived[j].Expression, text + "." + children[i].ChildText);
                            }

                            Assert.AreEqual(childrenReceived[j].Frame, frames[0]);
                            childrenReceived.RemoveAt(j);
                            break;
                        }
                    }
                    Assert.IsTrue(foundChild);
                }
                Assert.IsTrue(childrenReceived.Count == 0);
            }


            process.Continue();

            process.WaitForExit();
        }
示例#25
0
        private void StepTest(string filename, params ExpectedStep[] kinds)
        {
            var debugger = new PythonDebugger();

            string       fullPath = Path.GetFullPath(filename);
            string       dir      = Path.GetDirectoryName(filename);
            var          process  = debugger.CreateProcess(Version.Version, Version.Path, "\"" + fullPath + "\"", dir, "");
            PythonThread thread   = null;

            process.ThreadCreated += (sender, args) => {
                thread = args.Thread;
            };


            AutoResetEvent processEvent = new AutoResetEvent(false);

            bool processLoad = false, stepComplete = false;

            process.ProcessLoaded += (sender, args) => {
                processLoad = true;
                processEvent.Set();
            };

            process.StepComplete += (sender, args) => {
                stepComplete = true;
                processEvent.Set();
            };

            process.ExceptionRaised += (sender, args) => {
                args.Thread.Resume();
            };

            process.Start();

            for (int curStep = 0; curStep < kinds.Length; curStep++)
            {
                // process the stepping events as they occur, we cannot callback during the
                // event because the notificaiton happens on the debugger thread and we
                // need to callback to get the frames.
                processEvent.WaitOne();

                // first time through we hit process load, each additional time we should hit step complete.
                Debug.Assert((processLoad == true && stepComplete == false && curStep == 0) ||
                             (stepComplete == true && processLoad == false && curStep != 0));

                processLoad = stepComplete = false;

                var frames   = thread.GetFrames();
                var stepInfo = kinds[curStep];
                Assert.AreEqual(stepInfo.StartLine, frames[0].LineNo, String.Format("{0} != {1} on {2} step", stepInfo.StartLine, frames[0].LineNo, curStep));

                switch (stepInfo.Kind)
                {
                case StepKind.Into:
                    thread.StepInto();
                    break;

                case StepKind.Out:
                    thread.StepOut();
                    break;

                case StepKind.Over:
                    thread.StepOver();
                    break;

                case StepKind.Resume:
                    process.Resume();
                    break;
                }
            }

            process.WaitForExit();
        }