Пример #1
0
 internal static void AttachDebugger(VisualStudioProxy app, ProcessOutput proc, PythonDebugMode debugMode, string debugSecret, int debugPort)
 {
     if (debugMode == PythonDebugMode.PythonOnly)
     {
         string qualifierUri = string.Format("tcp://{0}@localhost:{1}", debugSecret, debugPort);
         while (!app.AttachToProcess(proc, PythonRemoteDebugPortSupplierUnsecuredId, qualifierUri))
         {
             if (proc.Wait(TimeSpan.FromMilliseconds(500)))
             {
                 break;
             }
         }
     }
     else if (debugMode == PythonDebugMode.PythonAndNative)
     {
         var engines = new[] { PythonDebugEngineGuid, NativeDebugEngineGuid };
         while (!app.AttachToProcess(proc, engines))
         {
             if (proc.Wait(TimeSpan.FromMilliseconds(500)))
             {
                 break;
             }
         }
     }
 }
Пример #2
0
            public void Run()
            {
                if (!File.Exists(_settings.InterpreterPath))
                {
                    Error(Strings.Test_InterpreterDoesNotExist.FormatUI(_settings.InterpreterPath));
                    return;
                }
                try {
                    DetachFromSillyManagedProcess();

                    var pythonPath = InitializeEnvironment();

                    string testList = null;
                    // For a small set of tests, we'll pass them on the command
                    // line. Once we exceed a certain (arbitrary) number, create
                    // a test list on disk so that we do not overflow the
                    // 32K argument limit.
                    if (_tests.Length > 5)
                    {
                        testList = CreateTestList();
                    }
                    var arguments = GetArguments(testList);

                    ////////////////////////////////////////////////////////////
                    // Do the test run
                    using (var proc = ProcessOutput.Run(
                               _settings.InterpreterPath,
                               arguments,
                               _settings.WorkingDirectory,
                               _env,
                               _showConsole,
                               null
                               )) {
                        bool killed = false;

                        DebugInfo("cd " + _settings.WorkingDirectory);
                        DebugInfo("set " + pythonPath.Key + "=" + pythonPath.Value);
                        DebugInfo(proc.Arguments);

                        _connected.WaitOne();
                        if (proc.ExitCode.HasValue)
                        {
                            // Process has already exited
                            proc.Wait();
                            Error(Strings.Test_FailedToStartExited);
                            if (proc.StandardErrorLines.Any())
                            {
                                foreach (var line in proc.StandardErrorLines)
                                {
                                    Error(line);
                                }
                            }
                        }

                        if (_debugMode != PythonDebugMode.None)
                        {
                            try {
                                if (_debugMode == PythonDebugMode.PythonOnly)
                                {
                                    string qualifierUri = string.Format("tcp://{0}@localhost:{1}", _debugSecret, _debugPort);
                                    while (!_app.AttachToProcess(proc, PythonRemoteDebugPortSupplierUnsecuredId, qualifierUri))
                                    {
                                        if (proc.Wait(TimeSpan.FromMilliseconds(500)))
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    var engines = new[] { PythonDebugEngineGuid, NativeDebugEngineGuid };
                                    while (!_app.AttachToProcess(proc, engines))
                                    {
                                        if (proc.Wait(TimeSpan.FromMilliseconds(500)))
                                        {
                                            break;
                                        }
                                    }
                                }
                            } catch (COMException ex) {
                                Error(Strings.Test_ErrorConnecting);
                                DebugError(ex.ToString());
                                try {
                                    proc.Kill();
                                } catch (InvalidOperationException) {
                                    // Process has already exited
                                }
                                killed = true;
                            }
                        }


                        // https://pytools.codeplex.com/workitem/2290
                        // Check that proc.WaitHandle was not null to avoid crashing if
                        // a test fails to start running. We will report failure and
                        // send the error message from stdout/stderr.
                        var handles = new WaitHandle[] { _cancelRequested, proc.WaitHandle, _done };
                        if (handles[1] == null)
                        {
                            killed = true;
                        }

                        if (!killed)
                        {
                            switch (WaitHandle.WaitAny(handles))
                            {
                            case 0:
                                // We've been cancelled
                                try {
                                    proc.Kill();
                                } catch (InvalidOperationException) {
                                    // Process has already exited
                                }
                                killed = true;
                                break;

                            case 1:
                                // The process has exited, give a chance for our comm channel
                                // to be flushed...
                                handles = new WaitHandle[] { _cancelRequested, _done };
                                if (WaitHandle.WaitAny(handles, 10000) != 1)
                                {
                                    Warning(Strings.Test_NoTestFinishedNotification);
                                }
                                break;

                            case 2:
                                // We received the done event
                                break;
                            }
                        }
                    }
                    if (File.Exists(testList))
                    {
                        try {
                            File.Delete(testList);
                        } catch (IOException) {
                        }
                    }
                } catch (Exception e) {
                    Error(e.ToString());
                }
            }
Пример #3
0
        private void RunTestCase(
            IFrameworkHandle frameworkHandle,
            IRunContext runContext,
            TestCase test,
            Dictionary <string, PythonProjectSettings> sourceToSettings
            )
        {
            var testResult = new TestResult(test);

            frameworkHandle.RecordStart(test);
            testResult.StartTime = DateTimeOffset.Now;

            PythonProjectSettings settings;

            if (!sourceToSettings.TryGetValue(test.Source, out settings))
            {
                sourceToSettings[test.Source] = settings = LoadProjectSettings(test.Source);
            }
            if (settings == null)
            {
                frameworkHandle.SendMessage(
                    TestMessageLevel.Error,
                    "Unable to determine interpreter to use for " + test.Source);
                RecordEnd(
                    frameworkHandle,
                    test,
                    testResult,
                    null,
                    "Unable to determine interpreter to use for " + test.Source,
                    TestOutcome.Failed);
                return;
            }

            var debugMode = PythonDebugMode.None;

            if (runContext.IsBeingDebugged && _app != null)
            {
                debugMode = settings.EnableNativeCodeDebugging ? PythonDebugMode.PythonAndNative : PythonDebugMode.PythonOnly;
            }

            var testCase = new PythonTestCase(settings, test, debugMode);

            var dte = _app != null?_app.GetDTE() : null;

            if (dte != null && debugMode != PythonDebugMode.None)
            {
                dte.Debugger.DetachAll();
            }

            if (!File.Exists(settings.Factory.Configuration.InterpreterPath))
            {
                frameworkHandle.SendMessage(TestMessageLevel.Error, "Interpreter path does not exist: " + settings.Factory.Configuration.InterpreterPath);
                return;
            }

            var env           = new Dictionary <string, string>();
            var pythonPathVar = settings.Factory.Configuration.PathEnvironmentVariable;
            var pythonPath    = testCase.SearchPaths;

            if (!string.IsNullOrWhiteSpace(pythonPathVar))
            {
                if (_app != null)
                {
                    var settingsManager = SettingsManagerCreator.GetSettingsManager(dte);
                    if (settingsManager != null)
                    {
                        var store = settingsManager.GetReadOnlySettingsStore(SettingsScope.UserSettings);
                        if (store != null && store.CollectionExists(@"PythonTools\Options\General"))
                        {
                            var  settingStr = store.GetString(@"PythonTools\Options\General", "ClearGlobalPythonPath", "True");
                            bool settingBool;
                            if (bool.TryParse(settingStr, out settingBool) && !settingBool)
                            {
                                pythonPath += ";" + Environment.GetEnvironmentVariable(pythonPathVar);
                            }
                        }
                    }
                }
                env[pythonPathVar] = pythonPath;
            }

            foreach (var envVar in testCase.Environment)
            {
                env[envVar.Key] = envVar.Value;
            }

            using (var proc = ProcessOutput.Run(
                       !settings.IsWindowsApplication ?
                       settings.Factory.Configuration.InterpreterPath :
                       settings.Factory.Configuration.WindowsInterpreterPath,
                       testCase.Arguments,
                       testCase.WorkingDirectory,
                       env,
                       false,
                       null
                       )) {
                bool killed = false;

#if DEBUG
                frameworkHandle.SendMessage(TestMessageLevel.Informational, "cd " + testCase.WorkingDirectory);
                frameworkHandle.SendMessage(TestMessageLevel.Informational, "set " + (pythonPathVar ?? "") + "=" + (pythonPath ?? ""));
                frameworkHandle.SendMessage(TestMessageLevel.Informational, proc.Arguments);
#endif

                proc.Wait(TimeSpan.FromMilliseconds(500));
                if (debugMode != PythonDebugMode.None)
                {
                    if (proc.ExitCode.HasValue)
                    {
                        // Process has already exited
                        frameworkHandle.SendMessage(TestMessageLevel.Error, "Failed to attach debugger because the process has already exited.");
                        if (proc.StandardErrorLines.Any())
                        {
                            frameworkHandle.SendMessage(TestMessageLevel.Error, "Standard error from Python:");
                            foreach (var line in proc.StandardErrorLines)
                            {
                                frameworkHandle.SendMessage(TestMessageLevel.Error, line);
                            }
                        }
                    }

                    try {
                        if (debugMode == PythonDebugMode.PythonOnly)
                        {
                            string qualifierUri = string.Format("tcp://{0}@localhost:{1}", testCase.DebugSecret, testCase.DebugPort);
                            while (!_app.AttachToProcess(proc, PythonRemoteDebugPortSupplierUnsecuredId, qualifierUri))
                            {
                                if (proc.Wait(TimeSpan.FromMilliseconds(500)))
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            var engines = new[] { PythonDebugEngineGuid, VSConstants.DebugEnginesGuids.NativeOnly_guid };
                            while (!_app.AttachToProcess(proc, engines))
                            {
                                if (proc.Wait(TimeSpan.FromMilliseconds(500)))
                                {
                                    break;
                                }
                            }
                        }

#if DEBUG
                    } catch (COMException ex) {
                        frameworkHandle.SendMessage(TestMessageLevel.Error, "Error occurred connecting to debuggee.");
                        frameworkHandle.SendMessage(TestMessageLevel.Error, ex.ToString());
                        try {
                            proc.Kill();
                        } catch (InvalidOperationException) {
                            // Process has already exited
                        }
                        killed = true;
                    }
#else
                    } catch (COMException) {