Exemplo n.º 1
0
        private static void PrintFirstTenMessages(string binLogFilePath)
        {
            var binLogReader = new BinLogReader();

            IEnumerable <Record> records;

            try
            {
                records = binLogReader.ReadRecords(binLogFilePath);
            }
            catch (Exception e)
            {
                PrintErrorMessage($"Exception while reading binlog: {e.Message}");
                return;
            }

            var count = 0;

            foreach (var record in records)
            {
                if (record.Args is BuildMessageEventArgs buildMessageEventArgs)
                {
                    Console.WriteLine(buildMessageEventArgs.Message);

                    if (++count == 10)
                    {
                        break;
                    }
                }
            }
        }
Exemplo n.º 2
0
        public static IEnumerable <string> PrintToLines(string path)
        {
            var reader = new BinLogReader();
            var eols   = new char [] { '\n', '\r' };

            foreach (var record in reader.ReadRecords(path))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                if (args.Message == null)
                {
                    continue;
                }

                foreach (var line in args.Message.Split(eols, System.StringSplitOptions.RemoveEmptyEntries))
                {
                    yield return(line);
                }
            }
        }
        /// <inheritdoc/>
        public override IEnumerable <IIssue> ReadIssues(
            MsBuildIssuesProvider issueProvider,
            IssueCommentFormat format,
            RepositorySettings repositorySettings,
            MsBuildIssuesSettings issueProviderSettings)
        {
#pragma warning disable SA1123 // Do not place regions within elements
            #region DupFinder Exclusion
#pragma warning restore SA1123 // Do not place regions within elements

            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            issueProviderSettings.NotNull(nameof(issueProviderSettings));

            #endregion

            var result = new List <IIssue>();

            var binLogReader = new BinLogReader();
            foreach (var record in binLogReader.ReadRecords(issueProviderSettings.LogFileContent))
            {
                var buildEventArgs = record.Args;

                if (buildEventArgs is BuildWarningEventArgs buildWarning)
                {
                    var projectFileRelativePath = this.GetProject(buildWarning, repositorySettings);

                    // Read affected file from the warning.
                    if (!this.TryGetFile(buildWarning, repositorySettings, out string fileName))
                    {
                        continue;
                    }

                    var line = GetLine(buildWarning);
                    var rule = buildWarning.Code;

                    // Determine rule URL.
                    Uri ruleUrl = null;
                    if (!string.IsNullOrWhiteSpace(rule))
                    {
                        ruleUrl = MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(rule);
                    }

                    // Build issue.
                    result.Add(
                        IssueBuilder
                        .NewIssue(buildWarning.Message, issueProvider)
                        .WithPriority(IssuePriority.Warning)
                        .InProject(projectFileRelativePath, System.IO.Path.GetFileNameWithoutExtension(projectFileRelativePath))
                        .InFile(fileName, line)
                        .OfRule(rule, ruleUrl)
                        .Create());
                }
            }

            return(result);
        }
Exemplo n.º 4
0
        //[Fact]
        //public void SearchPerf()
        //{
        //    var file = @"D:\contentsync.xml";
        //    var build = Serialization.Read(file);
        //    var sw = Stopwatch.StartNew();
        //    var search = new Search(build);
        //    var results = search.FindNodes("test");
        //    var elapsed = sw.Elapsed;
        //    MessageBox.Show(elapsed.ToString());
        //    File.WriteAllLines(@"D:\2.txt", results.Select(r => r.Field).ToArray());
        //}

        //[Fact]
        public void ReadBinaryLogRecords()
        {
            var reader  = new BinLogReader();
            var records = reader.ReadRecords(@"C:\temp\msbuild.binlog");

            foreach (var record in records)
            {
                var t = record.Args;
            }
        }
            public void Initialize()
            {
                if (binLogPath == null)
                {
                    return;
                }

                foreach (var invocation in BinLogReader.ExtractInvocations(binLogPath))
                {
                    InvocationsByProjectPath[invocation.ProjectFile] = invocation;
                }
            }
        public static long GetBinlogBlobSize(string filePath)
        {
            long result = 0;
            var  reader = new BinLogReader();

            reader.OnBlobRead += (kind, bytes) =>
            {
                result = bytes.LongLength;
            };
            var records = reader.ReadRecords(filePath);

            foreach (var record in records)
            {
                ;
            }

            return(result);
        }
        //[Fact]
        public void RecordStats()
        {
            var reader  = new BinLogReader();
            var records = reader.ReadRecords(@"C:\temp\vsmac.binlog");

            var recordsByType = new Dictionary <string, List <Microsoft.Build.Logging.Record> >();

            foreach (var record in records)
            {
                var args = record.Args;
                if (args == null)
                {
                    // probably a blob
                    continue;
                }

                string argsType = args.GetType().Name;
                if (!recordsByType.TryGetValue(argsType, out var bucket))
                {
                    bucket = new List <Microsoft.Build.Logging.Record>();
                    recordsByType[argsType] = bucket;
                }

                bucket.Add(record);
            }

            var mostRecords = recordsByType
                              .Select(kvp => (name: kvp.Key, count: kvp.Value.Count, totalLength: kvp.Value.Sum(r => r.Length), list: kvp.Value))
                              .OrderByDescending(t => t.totalLength)
                              .ToArray();

            foreach (var type in mostRecords)
            {
                type.list.Sort((l, r) => Math.Sign(r.Length - l.Length));
            }

            var messages      = mostRecords[0].list;
            var messageGroups = messages.GroupBy(m => GetMessageType(m.Args?.Message))
                                .Select(g => (g.Key, g.Count(), g.Sum(m => m.Args?.Message?.Length ?? 0), g.OrderByDescending(r => r.Length).ToArray()))
                                .OrderByDescending(g => g.Item3)
                                .ToArray();

            var projectStarted = mostRecords[1].list;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Analyzes an MSBuild binary log file.
        /// </summary>
        /// <param name="binLogPath">The path to the binary log file.</param>
        /// <param name="buildLoggers">MSBuild loggers to replay events from the log to.</param>
        /// <returns>A dictionary of target frameworks to <see cref="AnalyzerResult"/>.</returns>
        public AnalyzerResults Analyze(string binLogPath, IEnumerable <Microsoft.Build.Framework.ILogger> buildLoggers = null)
        {
            binLogPath = NormalizePath(binLogPath);
            if (!File.Exists(binLogPath))
            {
                throw new ArgumentException($"The path {binLogPath} could not be found.");
            }

            BinLogReader reader = new BinLogReader();

            using (EventProcessor eventProcessor = new EventProcessor(this, null, buildLoggers, reader, true))
            {
                reader.Replay(binLogPath);
                return(new AnalyzerResults
                {
                    { eventProcessor.Results, eventProcessor.OverallSuccess }
                });
            }
        }
Exemplo n.º 9
0
        public static void PrintBinLog(string path, StringBuilder sb)
        {
            var reader = new BinLogReader();

            foreach (var record in reader.ReadRecords(path))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                sb.AppendLine(args.Message);
            }
        }
Exemplo n.º 10
0
        public static IEnumerable <BuildEventArgs> ReadBuildEvents(string path)
        {
            var reader = new BinLogReader();

            foreach (var record in reader.ReadRecords(path))
            {
                if (record is null)
                {
                    continue;
                }

                if (record.Args is null)
                {
                    continue;
                }

                yield return(record.Args);
            }
        }
Exemplo n.º 11
0
        /// <inheritdoc/>
        public override IEnumerable <IIssue> ReadIssues(
            MsBuildIssuesProvider issueProvider,
            IRepositorySettings repositorySettings,
            MsBuildIssuesSettings issueProviderSettings)
        {
#pragma warning disable SA1123 // Do not place regions within elements
            #region DupFinder Exclusion
#pragma warning restore SA1123 // Do not place regions within elements

            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            issueProviderSettings.NotNull(nameof(issueProviderSettings));

            #endregion

            var result = new List <IIssue>();

            var binLogReader = new BinLogReader();
            foreach (var record in binLogReader.ReadRecords(issueProviderSettings.LogFileContent))
            {
                var buildEventArgs = record.Args;

                IIssue issue = null;
                if (buildEventArgs is BuildErrorEventArgs buildError)
                {
                    issue = this.GetIssue(buildError, issueProvider, repositorySettings);
                }
                else if (buildEventArgs is BuildWarningEventArgs buildWarning)
                {
                    issue = this.GetIssue(buildWarning, issueProvider, repositorySettings);
                }

                if (issue == null)
                {
                    continue;
                }

                result.Add(issue);
            }

            return(result);
        }
Exemplo n.º 12
0
        public static IEnumerable <string> PrintToLines(string path)
        {
            var reader = new BinLogReader();
            var eols   = new char [] { '\n', '\r' };

            foreach (var record in reader.ReadRecords(path))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                if (args.Message == null)
                {
                    continue;
                }

                if (args is ProjectStartedEventArgs psea)
                {
                    if (psea.Properties != null)
                    {
                        yield return("Initial Properties");

                        foreach (var prop in psea.Properties.Cast <System.Collections.DictionaryEntry> ().OrderBy(v => v.Key))
                        {
                            yield return($"{prop.Key} = {prop.Value}");
                        }
                    }
                }

                foreach (var line in args.Message.Split(eols, System.StringSplitOptions.RemoveEmptyEntries))
                {
                    yield return(line);
                }
            }
        }
        private static void ProcessFirstBinaryLog(string binaryLogFilePath, string binaryLogFilePath2, Dictionary <int, ProjectItem> projects)
        {
            var reader = new BinLogReader();

            foreach (var ev in reader.ReadRecords(binaryLogFilePath))
            {
                if (ev.Args?.BuildEventContext == null || ev.Args.BuildEventContext.ProjectInstanceId < 1)
                {
                    continue;
                }

                projects.AddIfProjectItem(ev);

                if (ev.Args is TaskStartedEventArgs taskStarted && taskStarted.TaskName == "Csc")
                {
                    var p = projects[taskStarted.BuildEventContext.ProjectInstanceId];
                    Debug.Assert(p.ProjectPath == taskStarted.ProjectFile);
                    p.IsCompiled = true;
                }

                if (binaryLogFilePath2 != null)
                {
                    projects.AddIfGenerateCompileDependencyCacheTarget(ev);
                }

                if (ev.Args is BuildMessageEventArgs msgEvent &&
                    msgEvent.Message != null &&
                    projects.TryGetValue(msgEvent.BuildEventContext.ProjectInstanceId, out var p2) &&
                    !p2.IsTrigger &&
                    (p2.IsDesignTimeBuild ? msgEvent.Message == DESIGN_TIME_BUILD_MSG : msgEvent.Message.Contains(MARKER)))
                {
                    if (binaryLogFilePath2 != null)
                    {
                        p2.CalcItemsToHash();
                    }

                    p2.IsTrigger = true;
                }
            }
        }
        private static void ProcessSecondBinaryLog(string binaryLogFilePath, ICollection <ProjectItem> projectRefs)
        {
            var reader   = new BinLogReader();
            var projects = new Dictionary <int, ProjectItem>();

            foreach (var ev in reader.ReadRecords(binaryLogFilePath))
            {
                if (ev.Args?.BuildEventContext == null || ev.Args.BuildEventContext.ProjectInstanceId < 1)
                {
                    continue;
                }

                projects.AddIfProjectItem(ev);
                var p = projects.AddIfGenerateCompileDependencyCacheTarget(ev);
                if (p != null)
                {
                    ProjectItem trigger;
                    if ((trigger = projectRefs.GetMatchingTrigger(ev)) != null)
                    {
                        trigger.DiffItemsToHash(p.CalcItemsToHash());
                    }
                }
            }
        }
Exemplo n.º 15
0
        public void ArchiveTest(ApplePlatform platform, string runtimeIdentifiers)
        {
            var project = "MySimpleApp";

            Configuration.IgnoreIfIgnoredPlatform(platform);

            var project_path = GetProjectPath(project, platform: platform);

            Clean(project_path);
            var properties = GetDefaultProperties(runtimeIdentifiers);

            properties ["ArchiveOnBuild"] = "true";

            var result           = DotNet.AssertBuild(project_path, properties);
            var reader           = new BinLogReader();
            var records          = reader.ReadRecords(result.BinLogPath).ToList();
            var findString       = "Output Property: ArchiveDir";
            var archiveDirRecord = records.Where(v => v?.Args?.Message?.Contains(findString) == true).ToList();

            Assert.That(archiveDirRecord.Count, Is.GreaterThan(0), "ArchiveDir");
            var archiveDir = archiveDirRecord [0].Args.Message.Substring(findString.Length + 1).Trim();

            Assert.That(archiveDir, Does.Exist, "Archive directory existence");
        }
Exemplo n.º 16
0
        public static IEnumerable <string> PrintToLines(string path)
        {
            var reader = new BinLogReader();
            var eols   = new char [] { '\n', '\r' };

            foreach (var record in reader.ReadRecords(path))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                if (args.Message == null)
                {
                    continue;
                }

                if (args is ProjectStartedEventArgs psea)
                {
                    if (psea.Properties != null)
                    {
                        yield return("Initial Properties");

                        var dict = psea.Properties as IDictionary <string, string>;
                        if (dict == null)
                        {
                            yield return($"Unknown property dictionary type: {psea.Properties.GetType ().FullName}");
                        }
                        else
                        {
                            foreach (var prop in dict.OrderBy(v => v.Key))
                            {
                                yield return($"{prop.Key} = {prop.Value}");
                            }
                        }
                    }
                }

                if (args is TaskParameterEventArgs tpea)
                {
                    switch (tpea.Kind)
                    {
                    case TaskParameterMessageKind.AddItem:
                        yield return("Added Item(s)");

                        break;

                    case TaskParameterMessageKind.RemoveItem:
                        yield return("Removed Item(s)");

                        break;

                    case TaskParameterMessageKind.TaskInput:
                        yield return("Task Parameter");

                        break;

                    case TaskParameterMessageKind.TaskOutput:
                        yield return("Output Item(s)");

                        break;

                    default:
                        yield return($"Unknown Kind ({tpea.Kind})");

                        break;
                    }
                    foreach (var item in tpea.Items)
                    {
                        var taskItem = item as ITaskItem;
                        yield return($"\t{tpea.ItemType}=");

                        if (taskItem != null)
                        {
                            yield return($"\t\t{taskItem.ItemSpec}");

                            foreach (var metadataName in taskItem.MetadataNames)
                            {
                                yield return($"\t\t\t{metadataName}={taskItem.GetMetadata (metadataName?.ToString ())}");
                            }
                        }
                        else
                        {
                            yield return($"\t{item}");
                        }
                    }
                    continue;
                }

                foreach (var line in args.Message.Split(eols, System.StringSplitOptions.RemoveEmptyEntries))
                {
                    yield return(line);
                }
            }
        }
Exemplo n.º 17
0
        public static IEnumerable <BuildLogEvent> GetBuildMessages(string path)
        {
            var reader = new BinLogReader();
            var eols   = new char [] { '\n', '\r' };

            foreach (var record in reader.ReadRecords(path))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                if (args is BuildErrorEventArgs buildError)
                {
                    var ea = buildError;
                    yield return(new BuildLogEvent {
                        Type = BuildLogEventType.Error,
                        File = ea.File,
                        LineNumber = ea.LineNumber,
                        EndLineNumber = ea.EndLineNumber,
                        ColumnNumber = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message = ea.Message,
                        ProjectFile = ea.ProjectFile,
                        Code = ea.Code,
                        SubCategory = ea.Subcategory,
                    });
                }
                else if (args is BuildWarningEventArgs buildWarning)
                {
                    var ea = buildWarning;
                    yield return(new BuildLogEvent {
                        Type = BuildLogEventType.Warning,
                        File = ea.File,
                        LineNumber = ea.LineNumber,
                        EndLineNumber = ea.EndLineNumber,
                        ColumnNumber = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message = ea.Message,
                        ProjectFile = ea.ProjectFile,
                        Code = ea.Code,
                        SubCategory = ea.Subcategory,
                    });
                }
                else if (args is BuildMessageEventArgs buildMessage)
                {
                    var ea = buildMessage;
                    yield return(new BuildLogEvent {
                        Type = BuildLogEventType.Message,
                        File = ea.File,
                        LineNumber = ea.LineNumber,
                        EndLineNumber = ea.EndLineNumber,
                        ColumnNumber = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message = ea.Message,
                        ProjectFile = ea.ProjectFile,
                        Code = ea.Code,
                        SubCategory = ea.Subcategory,
                    });
                }
            }
        }
Exemplo n.º 18
0
        public void ParseBinLog(string log)
        {
            ErrorEvents.Clear();
            WarningsEvents.Clear();
            MessageEvents.Clear();

            var reader = new BinLogReader();

            foreach (var record in reader.ReadRecords(log))
            {
                if (record == null)
                {
                    continue;
                }
                var args = record.Args;
                if (args == null)
                {
                    continue;
                }

                bool verbose = false;
                if (args is TaskStartedEventArgs tsea)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"TaskStartedEventArgs: {tsea.TaskName}");
                    }
                }
                else if (args is TaskFinishedEventArgs tfea)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"TaskFinished: {tfea.TaskName}");
                    }
                }
                else if (args is TargetStartedEventArgs targetStarted)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"TargetStartedEventArgs: {targetStarted.TargetName}");
                    }
                }
                else if (args is TargetFinishedEventArgs targetFinished)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"TargetFinishedEventArgs: {targetFinished.TargetName} Outputs: {targetFinished.TargetOutputs}");
                    }
                }
                else if (args is BuildStartedEventArgs buildStarted)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"BuildStarted: {buildStarted.Message}");
                    }
                }
                else if (args is BuildFinishedEventArgs buildFinished)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"BuildFinished: {buildFinished.Message}");
                    }
                }
                else if (args is ProjectEvaluationStartedEventArgs projectEvaluationStarted)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"ProjectEvaluationStarted: {projectEvaluationStarted.ProjectFile}");
                    }
                }
                else if (args.GetType().Name == "ProjectEvaluationFinishedEventArgs")
                {
                    if (verbose)
                    {
                        Console.WriteLine($"ProjectEvaluationFinished: {args}");
                    }
                }
                else if (args is ProjectStartedEventArgs projectStarted)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"ProjectStarted: {projectStarted.ProjectFile}");
                    }
                }
                else if (args is ProjectFinishedEventArgs projectFinished)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"ProjectFinished: {projectFinished.ProjectFile}");
                    }
                }
                else if (args is BuildErrorEventArgs buildError)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"❌ BuildError: {buildError.Message}");
                    }
                    var ea = buildError;
                    ErrorEvents.Add(new LogEvent {
                        File            = ea.File,
                        LineNumber      = ea.LineNumber,
                        EndLineNumber   = ea.EndLineNumber,
                        ColumnNumber    = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message         = ea.Message,
                        ProjectFile     = ea.ProjectFile,
                        Code            = ea.Code,
                        SubCategory     = ea.Subcategory,
                    });
                }
                else if (args is BuildWarningEventArgs buildWarning)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"⚠️ BuildWarning: {buildWarning.Message}");
                    }
                    var ea = buildWarning;
                    WarningsEvents.Add(new LogEvent {
                        File            = ea.File,
                        LineNumber      = ea.LineNumber,
                        EndLineNumber   = ea.EndLineNumber,
                        ColumnNumber    = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message         = ea.Message,
                        ProjectFile     = ea.ProjectFile,
                        Code            = ea.Code,
                        SubCategory     = ea.Subcategory,
                    });
                }
                else if (args is BuildMessageEventArgs buildMessage)
                {
                    if (verbose)
                    {
                        Console.WriteLine($"ℹ️ BuildMessage: {buildMessage.Message}");
                    }
                    var ea = buildMessage;
                    MessageEvents.Add(new LogEvent {
                        File            = ea.File,
                        LineNumber      = ea.LineNumber,
                        EndLineNumber   = ea.EndLineNumber,
                        ColumnNumber    = ea.ColumnNumber,
                        EndColumnNumber = ea.EndColumnNumber,
                        Message         = ea.Message,
                        ProjectFile     = ea.ProjectFile,
                        Code            = ea.Code,
                        SubCategory     = ea.Subcategory,
                    });
                }
                else
                {
                    Console.WriteLine($"‼️ Unknown record type: {args.GetType ().FullName}");
                }
            }
        }
        public void BundleIdentifierInPartialAppManifest()
        {
            // https://github.com/xamarin/xamarin-macios/issues/12051
            var csproj = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Project Sdk=""Microsoft.NET.Sdk"">
	<PropertyGroup>
		<TargetFramework>net6.0-macos</TargetFramework>
		<OutputType>Exe</OutputType>
    </PropertyGroup>

	<ItemGroup>
		<PartialAppManifest Include=""MyPartialManifest.plist"" />
	</ItemGroup>
</Project>";

            var partialPList = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version=""1.0"">
<dict>
        <key>CFBundleIdentifier</key>
        <string>com.xamarin.detectsigningidentitytest</string>
</dict>
</plist>";

            var tmpdir = Cache.CreateTemporaryDirectory();

            Configuration.CopyDotNetSupportingFiles(tmpdir);
            var csprojPath = Path.Combine(tmpdir, "BundleIdentifierInPartialAppManifest.csproj");

            File.WriteAllText(csprojPath, csproj);

            // Create an empty main app manifest
            var mainPListPath = Path.Combine(tmpdir, "Info.plist");

            new PDictionary().Save(mainPListPath);

            // Save our custom partial app manifest
            var partialPListPath = Path.Combine(tmpdir, "MyPartialManifest.plist");

            File.WriteAllText(partialPListPath, partialPList);

            var engine     = new BuildEngine();
            var properties = new Dictionary <string, string> {
                { "_CanOutputAppBundle", "true" },
            };
            var rv = engine.RunTarget(ApplePlatform.MacOSX, ExecutionMode.DotNet, csprojPath, target: "_DetectSigningIdentity", properties: properties);

            Assert.AreEqual(0, rv.ExitCode, "Exit code");

            // Find the BundleIdentifier parameter to the DetectSigningIdentity task.
            var reader    = new BinLogReader();
            var records   = reader.ReadRecords(rv.BinLogPath).ToList();
            var taskIndex = records.FindIndex(v => v?.Args is TaskStartedEventArgs tsea && tsea.TaskName == "DetectSigningIdentity");

            Assert.That(taskIndex, Is.GreaterThan(0), "Task index");
            var taskParameterIndex = records.FindIndex(taskIndex + 1, v => v?.Args is BuildMessageEventArgs bmea && bmea.Message.StartsWith("Task Parameter:BundleIdentifier="));

            Assert.That(taskParameterIndex, Is.GreaterThan(0), "Parameter index");
            var taskParameter    = (BuildMessageEventArgs)records [taskParameterIndex]?.Args;
            var bundleIdentifier = taskParameter.Message.Substring("Task Parameter:BundleIdentifier=".Length);

            Assert.AreEqual("com.xamarin.detectsigningidentitytest", bundleIdentifier, "Bundle identifier");
        }