Example #1
0
        internal static int RunArtifactPostProcessingIfNeeded(string testSessionCorrelationId, ParseResult parseResult, FeatureFlag featureFlag)
        {
            if (!featureFlag.IsEnabled(FeatureFlag.ARTIFACTS_POSTPROCESSING))
            {
                return(0);
            }

            // VSTest runner will save artifacts inside a temp folder if needed.
            string expectedArtifactDirectory = Path.Combine(Path.GetTempPath(), testSessionCorrelationId);

            if (!Directory.Exists(expectedArtifactDirectory))
            {
                VSTestTrace.SafeWriteTrace(() => "No artifact found, post-processing won't run.");
                return(0);
            }

            VSTestTrace.SafeWriteTrace(() => $"Artifacts directory found '{expectedArtifactDirectory}', running post-processing.");

            var artifactsPostProcessArgs = new List <string> {
                "--artifactsProcessingMode-postprocess", $"--testSessionCorrelationId:{testSessionCorrelationId}"
            };

            if (parseResult.HasOption(TestCommandParser.DiagOption))
            {
                artifactsPostProcessArgs.Add($"--diag:{parseResult.GetValueForOption(TestCommandParser.DiagOption)}");
            }

            try
            {
                return(new VSTestForwardingApp(artifactsPostProcessArgs).Execute());
            }
            finally
            {
                if (Directory.Exists(expectedArtifactDirectory))
                {
                    VSTestTrace.SafeWriteTrace(() => $"Cleaning artifact directory '{expectedArtifactDirectory}'.");
                    try
                    {
                        Directory.Delete(expectedArtifactDirectory, true);
                    }
                    catch (Exception ex)
                    {
                        VSTestTrace.SafeWriteTrace(() => $"Exception during artifact cleanup: \n{ex}");
                    }
                }
            }
        }
Example #2
0
        public static int Run(ParseResult parseResult)
        {
            parseResult.HandleDebugSwitch();

            FeatureFlag.Default.PrintFlagFeatureState();

            // We use also current process id for the correlation id for possible future usage in case we need to know the parent process
            // from the VSTest side.
            string testSessionCorrelationId = $"{Environment.ProcessId}_{Guid.NewGuid()}";

            string[] args = parseResult.GetArguments();

            if (VSTestTrace.TraceEnabled)
            {
                string commandLineParameters = "";
                if (args?.Length > 0)
                {
                    commandLineParameters = args.Aggregate((a, b) => $"{a} | {b}");
                }
                VSTestTrace.SafeWriteTrace(() => $"Argument list: '{commandLineParameters}'");
            }

            // settings parameters are after -- (including --), these should not be considered by the parser
            string[] settings = args.SkipWhile(a => a != "--").ToArray();
            // all parameters before --
            args = args.TakeWhile(a => a != "--").ToArray();

            // Fix for https://github.com/Microsoft/vstest/issues/1453
            // Run dll/exe directly using the VSTestForwardingApp
            if (ContainsBuiltTestSources(args))
            {
                return(ForwardToVSTestConsole(parseResult, args, settings, testSessionCorrelationId));
            }

            return(ForwardToMsbuild(parseResult, settings, testSessionCorrelationId));
        }
Example #3
0
        private static TestCommand FromParseResult(ParseResult result, string[] settings, string testSessionCorrelationId, string msbuildPath = null)
        {
            result.ShowHelpOrErrorIfAppropriate();

            var msbuildArgs = new List <string>()
            {
                "-target:VSTest",
                "-nodereuse:false", // workaround for https://github.com/Microsoft/vstest/issues/1503
                "-nologo"
            };

            msbuildArgs.AddRange(result.OptionValuesToBeForwarded(TestCommandParser.GetCommand()));

            msbuildArgs.AddRange(result.GetValueForArgument(TestCommandParser.SlnOrProjectArgument) ?? Array.Empty <string>());

            if (settings.Any())
            {
                // skip '--' and escape every \ to be \\ and every " to be \" to survive the next hop
                string[] escaped = settings.Skip(1).Select(s => s.Replace("\\", "\\\\").Replace("\"", "\\\"")).ToArray();

                string runSettingsArg = string.Join(";", escaped);
                msbuildArgs.Add($"-property:VSTestCLIRunSettings=\"{runSettingsArg}\"");
            }

            string verbosityArg = result.ForwardedOptionValues <IReadOnlyCollection <string> >(TestCommandParser.GetCommand(), "verbosity")?.SingleOrDefault() ?? null;

            if (verbosityArg != null)
            {
                string[] verbosity = verbosityArg.Split(':', 2);
                if (verbosity.Length == 2)
                {
                    msbuildArgs.Add($"-property:VSTestVerbosity={verbosity[1]}");
                }
            }

            if (FeatureFlag.Default.IsEnabled(FeatureFlag.ARTIFACTS_POSTPROCESSING))
            {
                // Add artifacts processing mode and test session id for the artifact post-processing
                msbuildArgs.Add("-property:VSTestArtifactsProcessingMode=collect");
                msbuildArgs.Add($"-property:VSTestSessionCorrelationId={testSessionCorrelationId}");
            }

            bool noRestore = result.HasOption(TestCommandParser.NoRestoreOption) || result.HasOption(TestCommandParser.NoBuildOption);

            TestCommand testCommand = new(
                msbuildArgs,
                noRestore,
                msbuildPath);

            // Apply environment variables provided by the user via --environment (-e) parameter, if present
            SetEnvironmentVariablesFromParameters(testCommand, result);

            // Set DOTNET_PATH if it isn't already set in the environment as it is required
            // by the testhost which uses the apphost feature (Windows only).
            (bool hasRootVariable, string rootVariableName, string rootValue) = VSTestForwardingApp.GetRootVariable();
            if (!hasRootVariable)
            {
                testCommand.EnvironmentVariable(rootVariableName, rootValue);
                VSTestTrace.SafeWriteTrace(() => $"Root variable set {rootVariableName}:{rootValue}");
            }

            VSTestTrace.SafeWriteTrace(() => $"Starting test using MSBuild with arguments '{testCommand.GetArgumentsToMSBuild()}' custom MSBuild path '{msbuildPath}' norestore '{noRestore}'");
            return(testCommand);
        }