예제 #1
0
        public void LocalReprRestrictionsTest() {
            // https://pytools.codeplex.com/workitem/931
            var filename = DebuggerTestPath + "LocalReprRestrictionsTest.py";
            var debugger = new PythonDebugger();

            PythonThread thread = null;
            AutoResetEvent loaded = new AutoResetEvent(false);
            var process =
                DebugProcess(
                    debugger,
                    filename,
                    (newproc, newthread) => {
                        var bp = newproc.AddBreakPoint(filename, 22);
                        bp.Add();
                        thread = newthread;
                        loaded.Set();
                    }
                );

            AutoResetEvent breakpointHit = new AutoResetEvent(false);
            process.BreakpointHit += (sender, args) => {
                breakpointHit.Set();
            };

            process.Start();
            try {
                AssertWaited(breakpointHit);

                // Handle order inconsitencies accross interpreters
                var parms = thread.Frames[0].Parameters;
                foreach (var local in thread.Frames[0].Locals) {
                    switch (local.Expression) {
                        case "s":
                            Assert.AreEqual("'01234567890123456789012345678901234567890123456789'", local.StringRepr);
                            break;
                        case "sa1":
                            Assert.AreEqual("['0123456789012345678...123456789']", local.StringRepr);
                            break;
                        case "sa2":
                            Assert.AreEqual("[['0123456789012345678...123456789'], ['0123456789012345678...123456789']]", local.StringRepr);
                            break;
                        case "sa3":
                            Assert.AreEqual("[[[...], [...]], [[...], [...]], [[...], [...]]]", local.StringRepr);
                            break;
                        case "sa4":
                            Assert.AreEqual("[[[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], ...]", local.StringRepr);
                            break;
                        case "n":
                            Assert.AreEqual(
                                Version.Version < PythonLanguageVersion.V30 ?
                                "12345678901234567890123456789012345678901234567890L" :
                                "12345678901234567890123456789012345678901234567890",
                                local.StringRepr);
                            break;
                        case "na1":
                            Assert.AreEqual(
                                Version.Version < PythonLanguageVersion.V30 ?
                                "[12345678901234567890...234567890L]" :
                                "[12345678901234567890...1234567890]",
                                local.StringRepr);
                            break;
                        case "na2":
                            Assert.AreEqual(
                                Version.Version < PythonLanguageVersion.V30 ?
                                "[[12345678901234567890...234567890L], [12345678901234567890...234567890L]]" :
                                "[[12345678901234567890...1234567890], [12345678901234567890...1234567890]]",
                                local.StringRepr);
                            break;
                        case "na3":
                            Assert.AreEqual("[[[...], [...]], [[...], [...]], [[...], [...]]]", local.StringRepr);
                            break;
                        case "na4":
                            Assert.AreEqual("[[[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], ...]", local.StringRepr);
                            break;
                        case "c":
                            Assert.AreEqual("my_class: 0123456789012345678901234567890123456789", local.StringRepr);
                            break;
                        case "ca1":
                            Assert.AreEqual("[my_class: 0123456789...0123456789]", local.StringRepr);
                            break;
                        case "ca2":
                            Assert.AreEqual("[[my_class: 0123456789...0123456789], [my_class: 0123456789...0123456789]]", local.StringRepr);
                            break;
                        case "ca3":
                            Assert.AreEqual("[[[...], [...]], [[...], [...]], [[...], [...]]]", local.StringRepr);
                            break;
                        case "ca4":
                            Assert.AreEqual("[[[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]], ...]", local.StringRepr);
                            break;
                        case "da1":
                            Assert.AreEqual("{'0123456789012345678...123456789': '0123456789012345678...123456789'}", local.StringRepr);
                            break;
                        case "da2":
                            Assert.AreEqual("{'0123456789012345678...123456789': {'0123456789012345678...123456789': '0123456789012345678...123456789'}, '1': {'0123456789012345678...123456789': '0123456789012345678...123456789'}}", local.StringRepr);
                            break;
                        case "da3":
                            Assert.AreEqual("{'0123456789012345678...123456789': {'0123456789012345678...123456789': {...}, '1': {...}}, '1': {'0123456789012345678...123456789': {...}, '1': {...}}, '2': {'0123456789012345678...123456789': {...}, '1': {...}}}", local.StringRepr);
                            break;
                        case "da4":
                            Assert.AreEqual("{'01': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '0123456789012345678...123456789': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '02': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '03': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '04': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '05': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '06': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '07': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '08': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '09': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '10': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '11': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '12': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, '13': {'0123456789012345678...123456789': {...}, '1': {...}, '2': {...}}, ...}", local.StringRepr);
                            break;
                        default:
                            break;
                    }
                }
            } finally {
                TerminateProcess(process);
            }
        }
예제 #2
0
        public void StepToEntryPoint() {
            // https://pytools.codeplex.com/workitem/1344
            var debugger = new PythonDebugger();

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

            process.Start();
            try {
                AssertWaited(loaded);
                Assert.IsTrue(thread.Frames[0].FileName.EndsWith("SteppingTest.py"), "did not break in SteppingTest.py; instead, " + thread.Frames[0].FileName);
                Assert.AreEqual(1, thread.Frames[0].StartLine);
            } finally {
                TerminateProcess(process);
            }
        }
예제 #3
0
        public void SetNextLineTest() {
            if (GetType() == typeof(DebuggerTestsIpy)) {
                //http://ironpython.codeplex.com/workitem/30129
                return;
            }

            var debugger = new PythonDebugger();
            PythonThread thread = null;
            AutoResetEvent processLoaded = new AutoResetEvent(false);
            var process =
                DebugProcess(
                    debugger,
                    Path.Combine(DebuggerTestPath, "SetNextLine.py"),
                    resumeOnProcessLoaded: false,
                    onLoaded: (newproc, newthread) => {
                        thread = newthread;
                        processLoaded.Set();
                    }
                );

            AutoResetEvent brkHit = new AutoResetEvent(false);
            AutoResetEvent stepDone = new AutoResetEvent(false);
            process.BreakpointHit += (sender, args) => {
                brkHit.Set();
            };
            process.StepComplete += (sender, args) => {
                stepDone.Set();
            };

            try {
                process.Start();

                AssertWaited(processLoaded);

                var moduleFrame = thread.Frames[0];
                Assert.AreEqual(1, moduleFrame.StartLine);
                if (GetType() != typeof(DebuggerTestsIpy)) {
                    Assert.AreEqual(13, moduleFrame.EndLine);
                }

                // skip over def f()
                Assert.IsTrue(moduleFrame.SetLineNumber(6), "failed to set line number to 6");

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

                process.Resume();
                AssertWaited(brkHit);

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

                // skip y = 100
                Assert.IsTrue(moduleFrame.SetLineNumber(9), "failed to set line number to 9");

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

                // z shouldn't be defined
                var frames = thread.Frames;
                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();
                AssertWaited(brkHit);

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

                process.Continue();
            } finally {
                WaitForExit(process);
            }
        }
예제 #4
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;
            });

            try {
                process.Start();
                AssertWaited(loaded);

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

                // let loop run
                for (int i = 0; i < 20; 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));
                }
            } finally {
                TerminateProcess(process);
            }
        }
예제 #5
0
        private void ChildTest(string filename, int lineNo, string text, int frame, 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();
            };

            try {
                process.Start();

                AssertWaited(brkHit);

                var frames = thread.Frames;

                AutoResetEvent evalComplete = new AutoResetEvent(false);
                PythonEvaluationResult evalRes = null;
                Console.WriteLine("Executing {0}", text);
                frames[frame].ExecuteText(text, (completion) => {
                    evalRes = completion;
                    evalComplete.Set();
                });

                AssertWaited(evalComplete);
                Assert.IsNotNull(evalRes, "didn't get evaluation result");

                if (children == null) {
                    Assert.IsFalse(evalRes.IsExpandable, "result should not be expandable");
                    Assert.IsNull(evalRes.GetChildren(Int32.MaxValue), "result should not have children");
                } else {
                    Assert.IsNull(evalRes.ExceptionText, "exception while evaluating: " + evalRes.ExceptionText);
                    Assert.IsTrue(evalRes.IsExpandable, "result is not expandable");
                    var childrenReceived = new List<PythonEvaluationResult>(evalRes.GetChildren(Int32.MaxValue));

                    Console.WriteLine("{0} children received:", childrenReceived.Count);
                    foreach (var childReceived in childrenReceived) {
                        Console.WriteLine("\t{0}\t{1}\t{2}\t{3}", childReceived.ChildName, childReceived.Expression, childReceived.StringRepr, childReceived.HexRepr);
                    }

                    Assert.AreEqual(children.Length, childrenReceived.Count, "received incorrect number of children");

                    for (int i = 0; i < children.Length; i++) {
                        var curChild = children[i];
                        Console.WriteLine("Finding: <{0}> (Repr: <{1}>)", curChild.ChildText, curChild.Repr ?? "(null)");

                        bool foundChild = false;
                        for (int j = 0; j < childrenReceived.Count; j++) {
                            var curReceived = childrenReceived[j];
                            Console.WriteLine("Candidate: <{0}> (Repr: <{1}>)", curReceived.ChildName, curReceived.StringRepr ?? "(null)");
                            if (ChildrenMatch(curChild, curReceived)) {
                                foundChild = true;

                                string expr = curChild.Expression;
                                if (expr == null) {
                                    if (curChild.ChildText.StartsWith("[")) {
                                        expr = text + curChild.ChildText;
                                    } else {
                                        expr = text + "." + curChild.ChildText;
                                    }
                                }

                                Assert.AreEqual(expr, curReceived.Expression);
                                Assert.AreEqual(frames[frame], curReceived.Frame);
                                childrenReceived.RemoveAt(j);
                                break;
                            }
                        }

                        Assert.IsTrue(foundChild, "failed to find " + curChild.ChildText + " found " + String.Join(", ", childrenReceived.Select(x => x.ChildName)));
                    }

                    Assert.AreEqual(0, childrenReceived.Count, "there's still some children left over which we didn't find");
                }
            } finally {
                process.Continue();
                WaitForExit(process);
            }
        }
예제 #6
0
        public void Test3xStdoutBuffer() {
            if (Version.Version.Is3x()) {
                var debugger = new PythonDebugger();

                bool gotOutput = false;
                var process = DebugProcess(debugger, Path.Combine(DebuggerTestPath, "StdoutBuffer3x.py"), (processObj, threadObj) => {
                    processObj.DebuggerOutput += (sender, args) => {
                        Assert.IsFalse(gotOutput, "got output more than once");
                        gotOutput = true;
                        Assert.AreEqual("fob", args.Output);
                    };
                }, debugOptions: PythonDebugOptions.RedirectOutput);

                StartAndWaitForExit(process);

                Assert.IsTrue(gotOutput, "failed to get output");
            }
        }
예제 #7
0
 private void TestException(
     PythonDebugger debugger,
     string filename,
     bool resumeProcess,
     ExceptionMode defaultExceptionMode,
     ICollection<KeyValuePair<string, ExceptionMode>> exceptionModes,
     params ExceptionInfo[] exceptions
 ) {
     TestException(debugger, filename, resumeProcess, defaultExceptionMode, exceptionModes, PythonDebugOptions.RedirectOutput, exceptions);
 }
예제 #8
0
        private new PythonProcess DebugProcess(PythonDebugger debugger, string filename, Action<PythonProcess, PythonThread> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string pythonExe = null) {
            string fullPath = Path.GetFullPath(filename);
            string dir = cwd ?? Path.GetFullPath(Path.GetDirectoryName(filename));
            var process = debugger.CreateProcess(Version.Version, pythonExe ?? Version.InterpreterPath, "\"" + fullPath + "\"", dir, "", interpreterOptions, debugOptions);
            process.ProcessLoaded += (sender, args) => {
                if (onLoaded != null) {
                    onLoaded(process, args.Thread);
                }
                if (resumeOnProcessLoaded) {
                    process.Resume();
                }
            };

            return process;
        }
예제 #9
0
        public void TestExceptions() {
            var debugger = new PythonDebugger();
            for (int i = 0; i < 2; i++) {
                TestException(debugger, Path.Combine(DebuggerTestPath, "SimpleException.py"), i == 0, ExceptionMode.Always, null,
                    new ExceptionInfo("Exception", 3)
                );

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

                TestException(debugger, DebuggerTestPath + ComplexExceptions, i == 0, ExceptionMode.Unhandled, new[] {
                    new KeyValuePair<string, ExceptionMode>(PickleModule + ".PickleError", ExceptionMode.Never)
                });
                TestException(debugger, DebuggerTestPath + ComplexExceptions, i == 0, ExceptionMode.Never, new[] {
                    new KeyValuePair<string, ExceptionMode>(PickleModule + ".PickleError", ExceptionMode.Always),
                    new KeyValuePair<string, ExceptionMode>("StopIteration", ExceptionMode.Unhandled),
                    new KeyValuePair<string, ExceptionMode>("NameError", ExceptionMode.Never),
                    new KeyValuePair<string, ExceptionMode>("Exception", ExceptionMode.Always | ExceptionMode.Unhandled),
                },
                    new ExceptionInfo(PickleModule + ".PickleError", 6),
                    new ExceptionInfo("Exception", 29),
                    new ExceptionInfo("Exception", 32)
                );

                TestException(debugger, DebuggerTestPath + "FinallyExceptions.py", i == 0, ExceptionMode.Unhandled, null,
                    new ExceptionInfo("Exception", 3)
                );

                if (Version.Version.Is2x()) {
                    TestException(debugger, Path.Combine(DebuggerTestPath, "UnicodeException.py"), i == 0, ExceptionMode.Always, null,
                        new ExceptionInfo("Exception", 3)
                    );
                }

                // Only the last exception in each file should be noticed.
                if (Version.Version <= PythonLanguageVersion.V25) {
                    TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException1_v25.py"), i == 0, ExceptionMode.Unhandled, null,
                        new ExceptionInfo("Exception", 57)
                    );
                } else if (Version.Version.Is3x()) {
                    TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException1_v3x.py"), i == 0, ExceptionMode.Unhandled, null,
                        new ExceptionInfo("Exception", 56)
                    );
                } else {
                    TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException1.py"), i == 0, ExceptionMode.Unhandled, null,
                        new ExceptionInfo("Exception", 81)
                    );
                }

                TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException2.py"), i == 0, ExceptionMode.Unhandled, null,
                    new ExceptionInfo("Exception", 16)
                );
                TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException3.py"), i == 0, ExceptionMode.Unhandled, null,
                    new ExceptionInfo("ValueError", 12)
                );
                TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException4.py"), i == 0, ExceptionMode.Unhandled, null,
                    // On IronPython, an unhandled exception will be repeatedly reported as raised as it bubbles up the stack.
                    // Everywhere else, it will only be reported once at the point where it is initially raised. 
                    this is DebuggerTestsIpy ?
                    new[] { new ExceptionInfo("OSError", 17), new ExceptionInfo("OSError", 32), new ExceptionInfo("OSError", 55) } :
                    new[] { new ExceptionInfo("OSError", 17) }
                );
                TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException5.py"), i == 0, ExceptionMode.Unhandled, null,
                    new ExceptionInfo("ValueError", 4)
                );
                TestException(debugger, Path.Combine(DebuggerTestPath, "UnhandledException6.py"), i == 0, ExceptionMode.Unhandled, null,
                    new ExceptionInfo("OSError", 12)
                );
            }
        }
예제 #10
0
        public void TestExceptionInEgg() {
            var debugger = new PythonDebugger();

            TestException(debugger, DebuggerTestPath + "EGGceptionOnImport.py", true, ExceptionMode.Always, null,
                // We only see the unhandled exception in our script
                new ExceptionInfo("ValueError", 7)
            );
            TestException(debugger, DebuggerTestPath + "EGGceptionOnImport.py", true, ExceptionMode.Unhandled, null);

            // We never see this exception because it is fully handled in the egg
            TestException(debugger, DebuggerTestPath + "EGGceptionOnCall.py", true, ExceptionMode.Always, null);
            TestException(debugger, DebuggerTestPath + "EGGceptionOnCall.py", true, ExceptionMode.Unhandled, null);

            TestException(debugger, DebuggerTestPath + "EGGceptionOnCallback.py", true, ExceptionMode.Always, null,
                new ExceptionInfo("ValueError", 7),
                new ExceptionInfo("TypeError", 10),
                new ExceptionInfo("TypeError", 13)
            );

            TestException(debugger, DebuggerTestPath + "EGGceptionOnCallback.py", true, ExceptionMode.Unhandled, null,
                new ExceptionInfo("TypeError", 13)
            );
        }
예제 #11
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(breakPoint, args.Breakpoint);
            };

            StartAndWaitForExit(process);

            Assert.IsTrue(bindFailed, "Should not have bound the breakpoint");
        }
예제 #12
0
        public void TestBreakpointHitOtherThreadStackTrace() {
            // http://pytools.codeplex.com/workitem/483

            var debugger = new PythonDebugger();
            string filename = Path.Combine(DebuggerTestPath, "ThreadJoin.py");
            PythonThread thread = null;
            var process = DebugProcess(debugger, filename, (newproc, newthread) => {
                thread = newthread;
                var bp = newproc.AddBreakPoint(filename, 5);
                bp.Add();
            },
                debugOptions: PythonDebugOptions.WaitOnAbnormalExit | PythonDebugOptions.WaitOnNormalExit
            );

            AutoResetEvent bpHit = new AutoResetEvent(false);

            ExceptionDispatchInfo exc = null;

            process.BreakpointHit += (sender, args) => {
                try {
                    Assert.AreNotEqual(args.Thread, thread, "breakpoint shouldn't be on main thread");

                    foreach (var frame in thread.Frames) {
                        Console.WriteLine(frame.FileName);
                        Console.WriteLine(frame.LineNo);
                    }
                    Assert.IsTrue(thread.Frames.Count > 1, "expected more than one frame");
                    process.Continue();
                } catch (Exception ex) {
                    exc = ExceptionDispatchInfo.Capture(ex);
                } finally {
                    bpHit.Set();
                }
            };

            process.Start();

            try {
                if (!bpHit.WaitOne(10000)) {
                    Assert.Fail("Failed to hit breakpoint");
                }
                if (exc != null) {
                    exc.Throw();
                }
            } finally {
                TerminateProcess(process);
            }
        }
예제 #13
0
        public void BreakStepStep() {
            // http://pytools.codeplex.com/workitem/815

            var debugger = new PythonDebugger();
            string fn = Path.Combine(DebuggerTestPath, "StepBreakBreak.py");
            var process = DebugProcess(debugger, fn, (newproc, newthread) => {
                PythonBreakpoint breakPoint = newproc.AddBreakPointByFileExtension(2, fn);
                breakPoint.Add();

                breakPoint = newproc.AddBreakPointByFileExtension(3, fn);
                breakPoint.Add();
            }, cwd: DebuggerTestPath);

            int hitBp = 0;
            process.BreakpointHit += (sender, args) => {
                ++hitBp;
                args.Thread.StepOver();
            };
            bool sentStep = false;
            process.StepComplete += (sender, args) => {
                if (sentStep) {
                    process.Continue();
                } else {
                    args.Thread.StepOver();
                    sentStep = true;
                }
            };
            StartAndWaitForExit(process);
        }
예제 #14
0
        public void TestWindowsStartup() {
            var debugger = new PythonDebugger();

            string pythonwExe = Path.Combine(Path.GetDirectoryName(Version.InterpreterPath), "pythonw.exe");
            if (!File.Exists(pythonwExe)) {
                pythonwExe = Path.Combine(Path.GetDirectoryName(Version.InterpreterPath), "ipyw.exe");
            }

            if (File.Exists(pythonwExe)) {
                // hello world
                TestExitCode(debugger, TestData.GetPath(@"TestData\HelloWorld\Program.py"), 0, pythonExe: pythonwExe);

                // test which calls sys.exit(23)
                TestExitCode(debugger, Path.Combine(DebuggerTestPath, "SysExit.py"), 23, pythonExe: pythonwExe);

                // test which calls raise Exception()
                TestExitCode(debugger, Path.Combine(DebuggerTestPath, "ExceptionalExit.py"), 1, pythonExe: pythonwExe);
            }
        }
예제 #15
0
        private void TestException(
            PythonDebugger debugger,
            string filename,
            bool resumeProcess,
            ExceptionMode defaultExceptionMode,
            ICollection<KeyValuePair<string, ExceptionMode>> exceptionModes,
            PythonDebugOptions debugOptions,
            params ExceptionInfo[] exceptions
        ) {
            Console.WriteLine();
            Console.WriteLine("Testing {0}", filename);

            bool loaded = false;
            var process = DebugProcess(debugger, filename, (processObj, threadObj) => {
                loaded = true;
                processObj.SetExceptionInfo(
                    (int)defaultExceptionMode,
                    exceptionModes == null ?
                        Enumerable.Empty<KeyValuePair<string, int>>() :
                        exceptionModes.Select(m => new KeyValuePair<string, int>(m.Key, (int)m.Value))
                );
            }, debugOptions: debugOptions);

            var raised = new List<Tuple<string, string>>();
            process.ExceptionRaised += (sender, args) => {
                if (loaded) {
                    raised.Add(Tuple.Create(args.Exception.TypeName, TryGetStack(args.Thread)));
                }
                if (resumeProcess) {
                    process.Resume();
                } else {
                    args.Thread.Resume();
                }
            };

            StartAndWaitForExit(process);

            if (Version.Version == PythonLanguageVersion.V30 && raised.Count > exceptions.Length) {
                // Python 3.0 raises an exception as the process shuts down.
                raised.RemoveAt(raised.Count - 1);
            }

            if (GetType() == typeof(DebuggerTestsIpy) && raised.Count == exceptions.Length + 1) {
                // IronPython over-reports exceptions
                raised.RemoveAt(raised.Count - 1);
            }

            foreach (var t in raised) {
                Console.WriteLine("Received {0} at{1}{2}", t.Item1, Environment.NewLine, t.Item2);
            }
            AssertUtil.AreEqual(
                raised.Select(t => t.Item1),
                exceptions.Select(e => e.TypeName).ToArray()
            );
        }
예제 #16
0
        private void TestExitCode(PythonDebugger debugger, string filename, int expectedExitCode, string interpreterOptions = null, string pythonExe = null) {
            var process = DebugProcess(debugger, filename, interpreterOptions: interpreterOptions, pythonExe: pythonExe);

            // Collect these values and assert on them on the main thread
            bool threadCreated = false, threadExited = false;
            bool processExited = false;
            int exitCode = -1000;
            var output = new StringBuilder();
            AutoResetEvent hasExited = new AutoResetEvent(false);
            process.ThreadCreated += (sender, args) => {
                threadCreated = true;
            };
            process.ThreadExited += (sender, args) => {
                threadExited = true;
            };
            process.ProcessExited += (sender, args) => {
                exitCode = args.ExitCode;
                processExited = true;
                hasExited.Set();
            };
            process.ExceptionRaised += (sender, args) => {
                process.Resume();
            };
            process.DebuggerOutput += (sender, args) => {
                if (args.Output != null) {
                    lock (output) {
                        output.AppendLine(args.Output);
                    }
                }
            };

            StartAndWaitForExit(process);
            // Only wait a little while - the process should have already exited
            // by the time we get here, but we may not have received the event
            // yet.
            Assert.IsTrue(hasExited.WaitOne(1000), "ProcessExited event was not raised");

            Console.WriteLine("Output from process:");
            Console.Write(output.ToString());
            Console.WriteLine("=== End of output ===");
            Assert.IsTrue(threadCreated, "Never got notification of thread creation");
            Assert.IsTrue(threadExited, "Process failed to exit");
            Assert.IsTrue(processExited, "Process failed to exit");
            Assert.AreEqual(expectedExitCode, exitCode, String.Format("Unexpected Python process exit code for '{0}'", filename));
        }
예제 #17
0
        public void TestExceptionsSysExitZero() {
            var debugger = new PythonDebugger();

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitNone.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.BreakOnSystemExitZero,
                new ExceptionInfo("SystemExit", 1)
            );

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitZeroRaise.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.BreakOnSystemExitZero,
                new ExceptionInfo("SystemExit", 1)
            );

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitZero.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.BreakOnSystemExitZero,
                new ExceptionInfo("SystemExit", 2)
            );

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitNone.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.RedirectOutput
            );

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitZeroRaise.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.RedirectOutput
            );

            TestException(
                debugger,
                Path.Combine(DebuggerTestPath, "SysExitZero.py"),
                true, ExceptionMode.Unhandled,
                null,
                PythonDebugOptions.RedirectOutput
            );
        }
예제 #18
0
        public void TestInterpreterArguments() {
            Version.AssertInstalled();
            var debugger = new PythonDebugger();

            // test which verifies we have no doc string when running w/ -OO
            TestExitCode(debugger, Path.Combine(DebuggerTestPath, "DocString.py"), 0, interpreterOptions: "-OO");
        }
예제 #19
0
        public void TestExceptionHandlers() {
            var debugger = new PythonDebugger();

            TestGetHandledExceptionRanges(debugger, Path.Combine(DebuggerTestPath, "ExceptionHandlers.py"),
                new ExceptionHandlerInfo(1, 3, "*"),
                new ExceptionHandlerInfo(6, 7, "*"),
                new ExceptionHandlerInfo(9, 13, "*"),

                new ExceptionHandlerInfo(18, 19, "ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BufferError", "BytesWarning", "DeprecationWarning", "EOFError", "EnvironmentError", "Exception", "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError", "ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", "NameError", "NotImplementedError", "OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError", "RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError", "SystemExit", "TabError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning", "ValueError", "Warning", "WindowsError", "ZeroDivisionError"),
                new ExceptionHandlerInfo(69, 70, "ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BufferError", "BytesWarning", "DeprecationWarning", "EOFError", "EnvironmentError", "Exception", "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError", "ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", "NameError", "NotImplementedError", "OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError", "RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError", "SystemExit", "TabError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning", "ValueError", "Warning", "WindowsError", "ZeroDivisionError"),
                new ExceptionHandlerInfo(72, 73, "*"),

                new ExceptionHandlerInfo(125, 126, "struct.error", "socket.error", "os.error"),
                new ExceptionHandlerInfo(130, 131, "struct.error", "socket.error", "os.error"),

                new ExceptionHandlerInfo(133, 143, "ValueError"),
                new ExceptionHandlerInfo(135, 141, "TypeError"),
                new ExceptionHandlerInfo(137, 139, "ValueError"),

                new ExceptionHandlerInfo(146, 148, "ValueError"),
                new ExceptionHandlerInfo(150, 156, "TypeError"),
                new ExceptionHandlerInfo(152, 154, "ValueError"),

                new ExceptionHandlerInfo(159, 160, "Exception"),
                new ExceptionHandlerInfo(162, 163, "Exception"),
                new ExceptionHandlerInfo(165, 166, "ValueError", "TypeError"),
                new ExceptionHandlerInfo(168, 169, "ValueError", "TypeError"),

                new ExceptionHandlerInfo(171, 172, "is_included", "also.included", "this.one.too.despite.having.lots.of.dots")
            );
        }
예제 #20
0
        public void TestOutputRedirection() {
            var debugger = new PythonDebugger();
            var expectedOutput = new Queue<string>(new[] { "stdout", "stderr" });

            var process = DebugProcess(debugger, Path.Combine(DebuggerTestPath, "Output.py"), (processObj, threadObj) => {
                processObj.DebuggerOutput += (sender, e) => {
                    if (expectedOutput.Count != 0) {
                        Assert.AreEqual(expectedOutput.Dequeue(), e.Output);
                    }
                };
            }, debugOptions: PythonDebugOptions.RedirectOutput);

            try {
                process.Start();
                Thread.Sleep(1000);
            } finally {
                WaitForExit(process);
            }
        }
예제 #21
0
        private void TestGetHandledExceptionRanges(PythonDebugger debugger, string filename, params ExceptionHandlerInfo[] expected) {
            var process = DebugProcess(debugger, filename, (processObj, threadObj) => { });

            var actual = process.GetHandledExceptionRanges(filename);
            Assert.AreEqual(expected.Length, actual.Count);

            Assert.IsTrue(actual.All(a =>
                expected.SingleOrDefault(e => e.FirstLine == a.Item1 && e.LastLine == a.Item2 && e.Expressions.ContainsExactly(a.Item3)) != null
            ));
        }
예제 #22
0
        public void TestInputFunction() {
            // 845 Python 3.3 Bad argument type for the debugger output wrappers
            // A change to the Python 3.3 implementation of input() now requires
            // that `errors` be set to a valid value on stdout. This test
            // ensures that calls to `input` continue to work.

            var debugger = new PythonDebugger();
            var expectedOutput = "Provide A: fob\n";
            string actualOutput = string.Empty;

            var process = DebugProcess(debugger, Path.Combine(DebuggerTestPath, "InputFunction.py"), (processObj, threadObj) => {
                processObj.DebuggerOutput += (sender, args) => {
                    actualOutput += args.Output;
                };
            }, debugOptions: PythonDebugOptions.RedirectOutput | PythonDebugOptions.RedirectInput);

            try {
                process.Start();
                Thread.Sleep(1000);
                process.SendStringToStdInput("fob\n");
            } finally {
                WaitForExit(process);
            }

            Assert.AreEqual(expectedOutput, actualOutput);
        }
예제 #23
0
        public void TestModuleLoad() {
            var debugger = new PythonDebugger();

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

            // imports are reported
            TestModuleLoad(debugger, Path.Combine(DebuggerTestPath, "imports_other.py"), "imports_other.py", "is_imported.py");
        }
예제 #24
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;
            });

            try {
                process.Start();
                AssertWaited(loaded);

                // 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();
                AssertWaited(breakComplete);

                Assert.AreEqual(thread, breakThread);

                process.Resume();
            } finally {
                TerminateProcess(process);
            }
        }
예제 #25
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);
            };

            StartAndWaitForExit(process);

            Assert.IsTrue(receivedFilenames.Count >= expectedModulesLoaded.Length, "did not receive enough module names");
            var set = new HashSet<string>();
            foreach (var received in receivedFilenames) {
                set.Add(Path.GetFileName(received));
            }

            AssertUtil.ContainsAtLeast(set, expectedModulesLoaded);
        }
예제 #26
0
        private void EvalTest(string filename, int lineNo, string frameName, int frameIndex, PythonEvaluationResultReprKind reprKind, 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();
            };

            try {
                process.Start();
                AssertWaited(brkHit);

                var frames = thread.Frames;

                PythonEvaluationResult obj = null;
                string errorMsg;
                if (eval.IsError) {
                    Assert.IsFalse(frames[frameIndex].TryParseText(eval.Expression, out errorMsg), "should not have been able to parse expression");
                    Assert.AreEqual(eval.ExceptionText, errorMsg);
                } else {
                    Assert.IsTrue(frames[frameIndex].TryParseText(eval.Expression, out errorMsg), "failed to parse expression");
                    Assert.IsNull(errorMsg);

                    Assert.AreEqual(frameName, frames[frameIndex].FunctionName);

                    var timeoutToken = new CancellationTokenSource(10000).Token;
                    obj = frames[frameIndex].ExecuteTextAsync(eval.Expression, reprKind)
                        .ContinueWith(t => t.Result, timeoutToken, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current)
                        .GetAwaiter().GetResult();

                    eval.Validate(obj);
                }

                process.Continue();
                WaitForExit(process);
                process = null;
            } finally {
                if (process != null) {
                    process.Terminate();
                    WaitForExit(process, assert: false);
                }
            }
        }
예제 #27
0
        public void TestStartup() {
            var debugger = new PythonDebugger();

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

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

            // test which calls raise Exception()
            TestExitCode(debugger, Path.Combine(DebuggerTestPath, "ExceptionalExit.py"), 1);

            // test which checks __name__ and __file__ to be correct
            TestExitCode(debugger, Path.Combine(DebuggerTestPath, "CheckNameAndFile.py"), 0);
        }
예제 #28
0
        public void StepStdLib() {
            // http://pytools.codeplex.com/workitem/504 - test option for stepping into std lib.
            var debugger = new PythonDebugger();

            string fullPath = Path.Combine(DebuggerTestPath, "StepStdLib.py");
            foreach (var steppingStdLib in new[] { false, true }) {
                var process = debugger.CreateProcess(
                    Version.Version,
                    Version.InterpreterPath,
                    "\"" + fullPath + "\"",
                    DebuggerTestPath,
                    "",
                    debugOptions: steppingStdLib ? (PythonDebugOptions.DebugStdLib | PythonDebugOptions.RedirectOutput) : PythonDebugOptions.RedirectOutput);

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

                AutoResetEvent processEvent = new AutoResetEvent(false);

                bool processLoad = false, stepComplete = false;
                PythonBreakpoint bp = null;
                process.ProcessLoaded += (sender, args) => {
                    bp = process.AddBreakPoint(fullPath, 2);
                    bp.Add();

                    processLoad = true;
                    processEvent.Set();
                };

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

                bool breakHit = false;
                process.BreakpointHit += (sender, args) => {
                    breakHit = true;
                    bp.Disable();
                    processEvent.Set();
                };

                process.Start();
                try {
                    AssertWaited(processEvent);
                    Assert.IsTrue(processLoad, "process did not load");
                    Assert.IsFalse(stepComplete, "step should not have completed");
                    process.Resume();

                    AssertWaited(processEvent);
                    Assert.IsTrue(breakHit, "breakpoint was not hit");

                    thread.StepInto();
                    AssertWaited(processEvent);
                    Assert.IsTrue(stepComplete, "step was not completed");

                    Debug.WriteLine(thread.Frames[thread.Frames.Count - 1].FileName);

                    if (steppingStdLib) {
                        Assert.IsTrue(thread.Frames[0].FileName.EndsWith("\\os.py"), "did not break in os.py; instead, " + thread.Frames[0].FileName);
                    } else {
                        Assert.IsTrue(thread.Frames[0].FileName.EndsWith("\\StepStdLib.py"), "did not break in StepStdLib.py; instead, " + thread.Frames[0].FileName);
                    }

                    process.Resume();
                } finally {
                    WaitForExit(process);
                }
            }
        }
예제 #29
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) => SafeSetEvent(brkHit);
                EventHandler<ProcessExitedEventArgs> processExitedHandler = (s, e) => SafeSetEvent(procExited);
                process.BreakpointHit += breakpointHitHandler;
                process.ProcessExited += processExitedHandler;

                try {
                    process.Start();
                } 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;
            }

            _evaluator.AttachProcess(process, new MockThreadIdMapper());
        }