예제 #1
0
        private static IEnumerable <string> GetDebugArgs(NodejsProjectSettings settings, out int port)
        {
            port = GetFreePort();

            return(new[] {
                "--debug-brk=" + port.ToString()
            });
        }
예제 #2
0
        /// <summary>
        /// This is the equivalent of "Run Selected Tests" functionality.
        /// </summary>
        /// <param name="tests">The list of TestCases selected to run</param>
        /// <param name="runContext">Defines the settings related to the current run</param>
        /// <param name="frameworkHandle">Handle to framework.  Used for recording results</param>
        public void RunTests(IEnumerable <TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle)
        {
            ValidateArg.NotNull(tests, "tests");
            ValidateArg.NotNull(runContext, "runContext");
            ValidateArg.NotNull(frameworkHandle, "frameworkHandle");
            _cancelRequested.Reset();

            // .ts file path -> project settings
            var fileToTests      = new Dictionary <string, List <TestCase> >();
            var sourceToSettings = new Dictionary <string, NodejsProjectSettings>();
            NodejsProjectSettings projectSettings = null;

            // put tests into dictionary where key is their source file
            foreach (var test in tests)
            {
                if (!fileToTests.ContainsKey(test.CodeFilePath))
                {
                    fileToTests[test.CodeFilePath] = new List <TestCase>();
                }
                fileToTests[test.CodeFilePath].Add(test);
            }

            // where key is the file and value is a list of tests
            foreach (var entry in fileToTests)
            {
                var firstTest = entry.Value.ElementAt(0);
                if (!sourceToSettings.TryGetValue(firstTest.Source, out projectSettings))
                {
                    sourceToSettings[firstTest.Source] = projectSettings = LoadProjectSettings(firstTest.Source);
                }

                _currentTests    = entry.Value;
                _frameworkHandle = frameworkHandle;

                // Run all test cases in a given file
                RunTestCases(entry.Value, runContext, frameworkHandle, projectSettings);
            }
        }
예제 #3
0
        private void RunTestCases(IEnumerable <TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle, NodejsProjectSettings settings)
        {
            // May be null, but this is handled by RunTestCase if it matters.
            // No VS instance just means no debugging, but everything else is
            // okay.
            if (tests.Count() == 0)
            {
                return;
            }

            using (var app = VisualStudioApp.FromEnvironmentVariable(NodejsConstants.NodeToolsProcessIdEnvironmentVariable))
            {
                var port     = 0;
                var nodeArgs = new List <string>();
                // .njsproj file path -> project settings
                var sourceToSettings = new Dictionary <string, NodejsProjectSettings>();
                var testObjects      = new List <TestCaseObject>();

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

                // All tests being run are for the same test file, so just use the first test listed to get the working dir
                var testInfo   = new NodejsTestInfo(tests.First().FullyQualifiedName);
                var workingDir = Path.GetDirectoryName(CommonUtils.GetAbsoluteFilePath(settings.WorkingDir, testInfo.ModulePath));

                var nodeVersion = Nodejs.GetNodeVersion(settings.NodeExePath);

                // We can only log telemetry when we're running in VS.
                // Since the required assemblies are not on disk if we're not running in VS, we have to reference them in a separate method
                // this way the .NET framework only tries to load the assemblies when we actually need them.
                if (app != null)
                {
                    LogTelemetry(tests.Count(), nodeVersion, runContext.IsBeingDebugged);
                }

                foreach (var test in tests)
                {
                    if (_cancelRequested.WaitOne(0))
                    {
                        break;
                    }

                    if (settings == null)
                    {
                        frameworkHandle.SendMessage(
                            TestMessageLevel.Error,
                            $"Unable to determine interpreter to use for {test.Source}.");
                        frameworkHandle.RecordEnd(test, TestOutcome.Failed);
                    }

                    var args = new List <string>();
                    args.AddRange(GetInterpreterArgs(test, workingDir, settings.ProjectRootDir));

                    // Fetch the run_tests argument for starting node.exe if not specified yet
                    if (nodeArgs.Count == 0 && args.Count > 0)
                    {
                        nodeArgs.Add(args[0]);
                    }

                    testObjects.Add(new TestCaseObject(args[1], args[2], args[3], args[4], args[5]));
                }

                if (runContext.IsBeingDebugged && app != null)
                {
                    app.GetDTE().Debugger.DetachAll();
                    // Ensure that --debug-brk is the first argument
                    nodeArgs.InsertRange(0, GetDebugArgs(out port));
                }

                _nodeProcess = ProcessOutput.Run(
                    settings.NodeExePath,
                    nodeArgs,
                    settings.WorkingDir,
                    /* env */ null,
                    /* visible */ false,
                    /* redirector */ new TestExecutionRedirector(this.ProcessTestRunnerEmit),
                    /* quote args */ false);

                if (runContext.IsBeingDebugged && app != null)
                {
                    try
                    {
                        //the '#ping=0' is a special flag to tell VS node debugger not to connect to the port,
                        //because a connection carries the consequence of setting off --debug-brk, and breakpoints will be missed.
                        var qualifierUri = string.Format("tcp://localhost:{0}#ping=0", port);
                        while (!app.AttachToProcess(_nodeProcess, NodejsRemoteDebugPortSupplierUnsecuredId, qualifierUri))
                        {
                            if (_nodeProcess.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());
                        KillNodeProcess();
                    }
#else
                    } catch (COMException) {
예제 #4
0
        private static IEnumerable<string> GetDebugArgs(NodejsProjectSettings settings, out int port) {
            port = GetFreePort();

            return new[] {
                "--debug-brk=" + port.ToString()
            };
        }