| File: OptProf\GenerateTrainingInputFiles.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.IO.Compression; 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> /// Generates OptProf training input files for VS components listed in OptProf.json file and /// their VSIX files located in the specified directory. /// </summary> public sealed class GenerateTrainingInputFiles : Microsoft.Build.Utilities.Task { /// <summary> /// Absolute path to the OptProf.json config file. /// </summary> [Required] public string ConfigurationFile { get; set; } /// <summary> /// Absolute path to the directory that contains VSIXes that will be inserted. /// </summary> [Required] public string InsertionDirectory { get; set; } /// <summary> /// Directory to output the results optprof data to. /// </summary> [Required] public string OutputDirectory { get; set; } public override bool Execute() { ExecuteImpl(); return !Log.HasLoggedErrors; } private void ExecuteImpl() { OptProfTrainingConfiguration config; try { config = OptProfTrainingConfiguration.Deserialize(File.ReadAllText(ConfigurationFile, Encoding.UTF8)); } catch (Exception e) { Log.LogError($"Unable to open the config file '{ConfigurationFile}': {e.Message}"); return; } if (config.Products == null) { Log.LogError($"Invalid configuration file format: missing 'products' element in '{ConfigurationFile}'."); } if (config.Assemblies == null) { Log.LogError($"Invalid configuration file format: missing 'assemblies' element in '{ConfigurationFile}'."); } if (!Directory.Exists(InsertionDirectory)) { Log.LogError($"Directory specified in InsertionDirectory does not exist: '{InsertionDirectory}'."); } if (Log.HasLoggedErrors) { return; } // Handle product entries foreach (var product in config.Products) { string vsixFilePath = Path.Combine(InsertionDirectory, product.Name); var jsonManifest = ReadVsixJsonManifest(vsixFilePath); var ibcEntries = IbcEntry.GetEntriesFromVsixJsonManifest(jsonManifest).ToArray(); WriteEntries(product.Tests, ibcEntries); } // Handle assembly entries foreach (var assembly in config.Assemblies) { var assemblyEntries = IbcEntry.GetEntriesFromAssembly(assembly).ToArray(); WriteEntries(assembly.Tests, assemblyEntries); } } private static JObject ReadVsixJsonManifest(string vsixPath) { using (var archive = new ZipArchive(File.Open(vsixPath, FileMode.Open), ZipArchiveMode.Read)) { var entry = archive.GetEntry("manifest.json"); using (var stream = entry.Open()) { using (var reader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 2048, leaveOpen: true)) { var content = reader.ReadToEnd(); return JObject.Parse(content); } } } } private void WriteEntries(OptProfTrainingTest[] tests, IbcEntry[] ibcEntries) { foreach (var test in tests) { var configurationsDir = Path.Combine(OutputDirectory, test.Container, "Configurations"); if (test.TestCases is object) { foreach (var fullyQualifiedName in test.TestCases) { WriteEntries(ibcEntries, Path.Combine(configurationsDir, fullyQualifiedName)); } } else if (test.FilteredTestCases is object) { foreach(var filteredTestCase in test.FilteredTestCases) { var filteredIbcEntries = ibcEntries.Where(ibc => ibc.EntryName == filteredTestCase.FileName).ToArray(); foreach (var fullyQualifiedName in filteredTestCase.TestCases) { WriteEntries(filteredIbcEntries, Path.Combine(configurationsDir, fullyQualifiedName)); } } } } } private static void WriteEntries(IbcEntry[] ibcEntries, string outDir) { Directory.CreateDirectory(outDir); foreach (var entry in ibcEntries) { int index = 0; string basePath = Path.Combine(outDir, entry.RelativeDirectoryPath.Replace("\\", "") + Path.GetFileNameWithoutExtension(entry.RelativeInstallationPath)); string fullPath; do { fullPath = basePath + "." + index + ".IBC.json"; index++; } while (File.Exists(fullPath)); using (var writer = new StreamWriter(File.Open(fullPath, FileMode.Create, FileAccess.Write, FileShare.Read))) { writer.WriteLine(entry.ToJson().ToString()); } } } } }