ValidateBinInspectResults.cs 3.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace Microsoft.DotNet.Build.Tasks
{
    // The BinInspect tool we use for signing validation does not support
    // baselining, this task is used to inspect the results and determine
    // if there is an actual failure we care about.
    public class ValidateBinInspectResults : BuildTask
    {
        private static readonly string s_RootElement = "DATA";
        private static readonly string s_RowElement = "ROW";
        private static readonly string s_ErrorElement = "Err";
        private static readonly string s_NameElement = "Full";
        private static readonly string s_ResultElement = "Pass";
        
        [Required]
        public string ResultsXml { get; set; }

        // list of Regex's to ignore 
        public ITaskItem [] BaselineFiles { get; set; }

        [Output]
        public ITaskItem[] ErrorResults { get; set; }

        public override bool Execute()
        {
            XDocument xdoc = XDocument.Load(ResultsXml);

            var rows = xdoc.Descendants(s_RootElement).Descendants(s_RowElement);
            
            List<ITaskItem> reportedFailures = new List<ITaskItem>();

            // Gather all of the rows with error results
            IEnumerable<XElement> errorRows = from descendant in rows
                            where descendant.Descendants().FirstOrDefault(f => f.Name == s_ResultElement).Value == "False"
                            select descendant;

            // Filter out baselined files which are stored as regex patterns
            HashSet<XElement> baselineExcludeElements = new HashSet<XElement>();
            if(BaselineFiles != null)
            {
                foreach(var baselineFile in BaselineFiles)
                {
52
                    IEnumerable<XElement> baselineExcluded = errorRows.Where(f => Regex.IsMatch(f.Descendants(s_NameElement).First().Value, baselineFile.ItemSpec, RegexOptions.IgnoreCase));
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
                    foreach(var baselineExclude in baselineExcluded)
                    {
                        baselineExcludeElements.Add(baselineExclude);
                    }
                }
            }
            // Gather the results with baselined files filtered out
            IEnumerable<XElement> baselinedRows = errorRows.Except(baselineExcludeElements);

            foreach (var filteredRow in baselinedRows)
            {
                ITaskItem item = new TaskItem(filteredRow.Descendants(s_NameElement).First().Value);
                item.SetMetadata("Error", filteredRow.Descendants(s_ErrorElement).First().Value);
                reportedFailures.Add(item);
            }

            ErrorResults = reportedFailures.ToArray();
            foreach(var result in ErrorResults)
            {
                Log.LogError($"{result.ItemSpec} failed with error {result.GetMetadata("Error")}");
            }
            return !Log.HasLoggedErrors;
        }
    }
}