| File: OptProf\GetRunSettingsSessionConfiguration.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.Build.Tasks.VisualStudio\Microsoft.DotNet.Build.Tasks.VisualStudio.csproj (Microsoft.DotNet.Build.Tasks.VisualStudio) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.IO; using System.Linq; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Newtonsoft.Json.Linq; namespace Microsoft.DotNet.Build.Tasks.VisualStudio { /// <summary> /// Calculates the SessionConfiguration to be used in .runsettings for OptProf training /// based on given OptProf.json configuration and VS bootstrapper information. /// </summary> public sealed class GetRunSettingsSessionConfiguration : Microsoft.Build.Utilities.Task { /// <summary> /// Absolute path to the OptProf.json config file. /// </summary> [Required] public string ConfigurationFile { get; set; } /// <summary> /// Product drop name, e.g. 'Products/$(System.TeamProject)/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber)' /// </summary> [Required] public string ProductDropName { get; set; } /// <summary> /// Path to the BootstrapperInfo.json /// </summary> [Required] public string BootstrapperInfoPath { get; set; } /// <summary> /// Contents of SessionConfiguration node of the .runsettings file. /// </summary> [Output] public string SessionConfiguration { get; private set; } public override bool Execute() { ExecuteImpl(); return !Log.HasLoggedErrors; } private void ExecuteImpl() { try { var profilingInputsDropName = GetProfilingInputsDropName(ProductDropName); var buildDropName = GetTestsDropName(File.ReadAllText(BootstrapperInfoPath, Encoding.UTF8)); var (testContainersString, testCaseFilterString) = GetTestContainersAndFilters(File.ReadAllText(ConfigurationFile, Encoding.UTF8), ConfigurationFile); SessionConfiguration = $@"<TestStores> <TestStore Uri=""vstsdrop:{profilingInputsDropName}"" /> <TestStore Uri=""vstsdrop:{buildDropName}"" /> </TestStores> <TestContainers> {testContainersString} </TestContainers> <TestCaseFilter>{testCaseFilterString}</TestCaseFilter>"; } catch (ApplicationException e) { Log.LogError(e.Message); } } internal static string GetTestsDropName(string bootstrapperInfoJson) { try { var jsonContent = JToken.Parse(bootstrapperInfoJson); var dropUrl = (string)((JArray)jsonContent).First["BuildDrop"]; const string prefix = "https://vsdrop.corp.microsoft.com/file/v1/Products/"; if (!dropUrl.StartsWith(prefix, StringComparison.Ordinal)) { throw new ApplicationException($"Invalid drop URL: '{dropUrl}'"); } return $"Tests/{dropUrl.Substring(prefix.Length)}"; } catch (Exception e) { throw new InvalidDataException( $"Unable to read bootstrapper info: {e.Message}{Environment.NewLine}" + $"Content of BootstrapperInfo.json:{Environment.NewLine}" + $"{bootstrapperInfoJson}"); } } private static string GetProfilingInputsDropName(string vsDropName) { const string prefix = "Products/"; if (!vsDropName.StartsWith(prefix, StringComparison.Ordinal)) { throw new ApplicationException("Invalid value of vsDropName argument: must start with 'Products/'."); } return "ProfilingInputs/" + vsDropName.Substring(prefix.Length); } internal static (string containers, string filters) GetTestContainersAndFilters(string configJson, string configPath) { try { var config = OptProfTrainingConfiguration.Deserialize(configJson); return (GetTestContainers(config), GetTestFilters(config)); } catch (Exception e) { throw new ApplicationException($"Unable to read config file '{configPath}': {e.Message}"); } } private static string GetTestContainers(OptProfTrainingConfiguration config) { var productContainers = config.Products?.Any() == true ? config.Products.SelectMany(x => x.Tests.Select(y => y.Container + ".dll")) : Enumerable.Empty<string>(); var assemblyContainers = config.Assemblies?.Any() == true ? config.Assemblies.SelectMany(x => x.Tests.Select(y => y.Container + ".dll")) : Enumerable.Empty<string>(); return string.Join( Environment.NewLine, productContainers .Concat(assemblyContainers) .Distinct() .Select(x => $@" <TestContainer FileName=""{x}"" />")); } private static string GetTestFilters(OptProfTrainingConfiguration config) { var productTests = config.Products?.Any() == true ? config.Products.SelectMany(x => x.Tests.SelectMany(y => y.TestCases ?? y.FilteredTestCases.SelectMany(z => z.TestCases))) : Enumerable.Empty<string>(); var assemblyTests = config.Assemblies?.Any() == true ? config.Assemblies.SelectMany(x => x.Tests.SelectMany(y => y.TestCases)) : Enumerable.Empty<string>(); return string.Join( "|", productTests .Concat(assemblyTests) .Distinct() .Select(x => $"FullyQualifiedName={x}")); } } }