File: OptProfCheckerUtil.cs
Web Access
Project: src\src\Tools\BuildBoss\BuildBoss.csproj (BuildBoss)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
 
namespace BuildBoss
{
    internal sealed class OptProfCheckerUtil : ICheckerUtil
    {
        private readonly string RepositoryDirectory;
        private readonly string ArtifactsDirectory;
        private readonly string Configuration;
        private readonly string OptProfFile;
 
        public OptProfCheckerUtil(string repositoryDirectory, string artifactsDirectory, string configuration)
        {
            RepositoryDirectory = repositoryDirectory;
            ArtifactsDirectory = artifactsDirectory;
            Configuration = configuration;
            OptProfFile = Path.Combine(RepositoryDirectory, "eng", "config", "OptProf.json");
        }
 
        public bool Check(TextWriter textWriter)
        {
            try
            {
                // check the optprof file exists, and load it if so
                if (!File.Exists(OptProfFile))
                {
                    textWriter.WriteLine($"Couldn't find OptProf file: {OptProfFile}");
                    return false;
                }
                var content = File.ReadAllText(OptProfFile);
                var optProfFile = JObject.Parse(content);
 
                // validate that each vsix listed in it is valid
                bool allGood = true;
                foreach (var product in optProfFile["products"])
                {
                    allGood &= CheckVsix(textWriter, product["name"].ToString(), product["tests"]);
                }
                return allGood;
            }
            catch (Exception ex)
            {
                textWriter.WriteLine($"Error verifying: {ex.Message}");
                return false;
            }
        }
 
        private bool CheckVsix(TextWriter textWriter, string vsixName, JToken tests)
        {
            string vsixRoot = Path.Combine(ArtifactsDirectory, "VSSetup", Configuration, "Insertion");
            string vsixFullPath = Path.Combine(vsixRoot, vsixName);
 
            // check vsix exists
            if (!File.Exists(vsixFullPath))
            {
                textWriter.WriteLine($"Product '{vsixName}' does not exist in '{vsixRoot}'");
                return false;
            }
 
            // read the manifest and extract the file list
            var manifestFileNames = GetManifestFileNames(textWriter, vsixFullPath);
 
            // check any filtered tests match what's in the vsix
            bool allGood = true;
            foreach (var test in tests)
            {
                string container = test["container"].ToString();
                var filteredTests = test["filteredTestCases"];
                if (filteredTests is object)
                {
                    foreach (var filteredTest in filteredTests)
                    {
                        var filename = filteredTest["filename"].ToString();
                        if (!manifestFileNames.Contains(filename))
                        {
                            allGood = false;
                            textWriter.WriteLine($"Failed to find file '{filename}' in '{vsixName}' (Container: {container})");
                        }
                    }
                }
            }
            return allGood;
        }
 
        private static HashSet<string> GetManifestFileNames(TextWriter textWriter, string vsixFullPath)
        {
            try
            {
                using (var archive = new ZipArchive(File.Open(vsixFullPath, 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();
                    var manifest = JObject.Parse(content);
                    return manifest["files"].Select(f => f["fileName"].ToString()).ToHashSet();
                }
            }
            catch (Exception)
            {
                textWriter.WriteLine($"Failed to read manifest from '{vsixFullPath}'");
                throw;
            }
        }
    }
}