// ReSharper disable once MemberCanBeMadeStatic.Local
        private void AnnotateTargets(Summary summary, CompetitionState competitionState)
        {
            var competitionTargets = TargetsSlot[summary];
            var targetsToAnnotate  = competitionTargets.Values
                                     .Where(t => t.HasUnsavedChanges)
                                     .ToArray();

            if (targetsToAnnotate.Length == 0)
            {
                return;
            }

            if (competitionState.HasCriticalErrorsInRun)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Warning,
                    "Source annotation skipped as there are critical errors in the run. Check the log please.");
                return;
            }

            var annotatedTargets = SourceAnnotationsHelper.TryAnnotateBenchmarkFiles(
                targetsToAnnotate, competitionState);

            if (annotatedTargets.Any())
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Warning,
                    "The sources were updated with new annotations. Please check them before commiting the changes.");
            }

            foreach (var competitionTarget in targetsToAnnotate)
            {
                competitionTarget.MarkAsSaved();
            }
        }
        /// <summary>
        /// Refills the competition targets collection and fills competition limits from the <see cref="PreviousRunLogUri"/>.
        /// </summary>
        /// <param name="competitionTargets">The collection to be filled with competition targets.</param>
        /// <param name="summary">Summary for the run.</param>
        /// <param name="competitionState">State of the run.</param>
        protected override void FillCompetitionTargets(
            CompetitionTargets competitionTargets, Summary summary, CompetitionState competitionState)
        {
            base.FillCompetitionTargets(competitionTargets, summary, competitionState);

            if (string.IsNullOrEmpty(PreviousRunLogUri))
            {
                return;
            }

            var xmlAnnotationDocs = ReadXmlAnnotationDocsFromLog(summary, competitionState);

            if (xmlAnnotationDocs.Length == 0)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Warning,
                    $"No XML annotation documents in the log '{PreviousRunLogUri}'.");

                return;
            }

            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (TryFillCompetitionTargetsFromLog(competitionTargets, xmlAnnotationDocs, competitionState))
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Informational,
                    $"Competition limits were updated from log file '{PreviousRunLogUri}'.");
            }
            else
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Informational,
                    $"Competition limits do not require update. Log file: '{PreviousRunLogUri}'.");
            }
        }
        private bool CheckPreconditions(Summary summary, CompetitionState competitionState)
        {
            if (summary.HasCriticalValidationErrors)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.ExecutionError,
                    "Summary has validation errors.");
            }

            var benchmarksWithReports = summary.Reports
                                        .Where(r => r.ExecuteResults.Any())
                                        .Select(r => r.Benchmark);

            var benchMissing = summary.GetSummaryOrderBenchmarks()
                               .Except(benchmarksWithReports)
                               .Select(b => b.Target.MethodTitle)
                               .Distinct()
                               .ToArray();

            if (benchMissing.Any())
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.ExecutionError,
                    "No reports for benchmarks: " + string.Join(", ", benchMissing));
            }

            if (CompetitionLimitProvider == null)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"The {nameof(CompetitionLimitProvider)} should be not null.");
            }

            return(!competitionState.HasCriticalErrorsInRun);
        }
        /// <summary>Refills the competition targets collection.</summary>
        /// <param name="competitionTargets">The collection to be filled with competition targets.</param>
        /// <param name="summary">Summary for the run.</param>
        /// <param name="competitionState">State of the run.</param>
        protected virtual void FillCompetitionTargets(
            CompetitionTargets competitionTargets,
            Summary summary,
            CompetitionState competitionState)
        {
            // DONTTOUCH: DO NOT add return into the if clause.
            // The competitionTargets should be filled with empty limits if IgnoreExistingAnnotations set to false
            if (IgnoreExistingAnnotations)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser,
                    MessageSeverity.Informational,
                    $"Existing benchmark limits are ignored due to {nameof(IgnoreExistingAnnotations)} setting.");
            }

            bool hasBaseline = false;

            competitionTargets.Clear();

            var targets = summary.GetExecutionOrderBenchmarks()
                          .Select(b => b.Target)
                          .ToHashSet();

            if (targets.Count == 0)
            {
                return;
            }

            var targetType = targets.First().Type;

            var competitionMetadata = AttributeAnnotations.TryGetCompetitionMetadata(targetType);

            foreach (var target in targets)
            {
                hasBaseline |= target.Baseline;

                var competitionTarget = TryParseCompetitionTarget(target, competitionMetadata, competitionState);
                if (competitionTarget != null)
                {
                    competitionTargets.Add(target.Method, competitionTarget);
                }
            }

            if (!hasBaseline && competitionTargets.Any())
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"The benchmark {targetType.Name} has no baseline.");
            }
        }
        // ReSharper disable once SuggestBaseTypeForParameter
        private bool TryFillCompetitionTargetsFromLog(
            CompetitionTargets competitionTargets, XDocument[] xmlAnnotationDocs, CompetitionState competitionState)
        {
            competitionState.Logger.WriteLineInfo(
                $"{LogVerbosePrefix} Parsing XML annotations ({xmlAnnotationDocs.Length} doc(s)) from log '{PreviousRunLogUri}'.");

            bool updated = false;

            foreach (var competitionTarget in competitionTargets.Values)
            {
                bool hasAnnotations = false;

                foreach (var doc in xmlAnnotationDocs)
                {
                    var parsedLimit = XmlAnnotations.TryParseCompetitionLimit(competitionTarget.Target, doc, competitionState);
                    if (parsedLimit != null)
                    {
                        hasAnnotations = true;
                        updated       |= competitionTarget.UnionWith(parsedLimit);
                    }
                }

                if (!hasAnnotations)
                {
                    competitionState.WriteMessage(
                        MessageSource.Analyser, MessageSeverity.Warning,
                        $"No logged XML annotation for {competitionTarget.Target.MethodTitle} found. Check if the method was renamed.");
                }
            }

            return(updated);
        }
Esempio n. 6
0
        private static double?TryParseLimitValue(
            Target target, XElement competitionNode,
            CompetitionLimitProperties limitProperty,
            CompetitionState competitionState)
        {
            double?result = null;

            var limitText = competitionNode.Attribute(limitProperty.ToString())?.Value;

            if (limitText != null)
            {
                var    culture = EnvironmentInfo.MainCultureInfo;
                double parsed;
                if (double.TryParse(limitText, NumberStyles.Any, culture, out parsed))
                {
                    result = parsed;
                }
                else
                {
                    competitionState.WriteMessage(
                        MessageSource.Analyser, MessageSeverity.SetupError,
                        $"XML anotation for {target.MethodTitle}: could not parse {limitProperty}.");
                }
            }

            return(result);
        }
Esempio n. 7
0
        public static XDocument TryParseXmlAnnotationDoc(
            [NotNull] Assembly assembly,
            [NotNull] string resourceName,
            bool useFullTypeName,
            [NotNull] CompetitionState competitionState)
        {
            Code.NotNull(assembly, nameof(assembly));
            Code.NotNullNorEmpty(resourceName, nameof(resourceName));
            Code.NotNull(competitionState, nameof(competitionState));

            using (var resourceStream = assembly.GetManifestResourceStream(resourceName))
            {
                if (resourceStream == null)
                {
                    competitionState.WriteMessage(
                        MessageSource.Analyser, MessageSeverity.SetupError,
                        $"Benchmark {assembly.FullName}: resource stream '{resourceName}' not found.");

                    return(null);
                }

                using (var reader = new StreamReader(resourceStream))
                {
                    return(TryParseXmlAnnotationDoc(
                               reader, useFullTypeName, competitionState,
                               $"Resource '{resourceName}'"));
                }
            }
        }
Esempio n. 8
0
        public static XDocument TryParseXmlAnnotationDoc(
            [NotNull] TextReader source,
            bool useFullTypeName,
            [NotNull] CompetitionState competitionState,
            [NotNull] string sourceDescription)
        {
            Code.NotNull(source, nameof(source));
            Code.NotNull(competitionState, nameof(competitionState));
            Code.NotNullNorEmpty(sourceDescription, nameof(sourceDescription));

            XDocument xmlAnnotationDoc;

            try
            {
                using (var reader = XmlReader.Create(source, GetXmlReaderSettings()))
                {
                    xmlAnnotationDoc = XDocument.Load(reader);
                    if (useFullTypeName)
                    {
                        MarkAsUsesFullTypeName(xmlAnnotationDoc);
                    }
                }
            }
            catch (ArgumentException ex)
            {
                competitionState.WriteExceptionMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"{sourceDescription}: Could not parse annotation.", ex);
                return(null);
            }
            catch (XmlException ex)
            {
                competitionState.WriteExceptionMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"{sourceDescription}: Could not parse annotation.", ex);
                return(null);
            }

            var rootNode = xmlAnnotationDoc.Element(CompetitionBenchmarksRootNode);

            if (rootNode == null)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"{sourceDescription}: root node {CompetitionBenchmarksRootNode} not found.");

                return(null);
            }

            return(xmlAnnotationDoc);
        }
        private void CheckCompetitionLimitsCore(Summary summary, CompetitionState competitionState, List <IWarning> warnings)
        {
            var checkPassed = CheckCompetitionLimits(summary, competitionState, warnings);

            CheckPostconditions(summary, competitionState, warnings);

            OnLimitsCheckCompleted(summary, competitionState, checkPassed);

            if (warnings.Count == 0)
            {
                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.Informational,
                    $"{GetType().Name}: All competition limits are ok.");
            }
        }
        private CompetitionLimit TryParseCompetitionLimit(
            Target target,
            CompetitionMetadata competitionMetadata,
            CompetitionState competitionState)
        {
            CompetitionLimit result = null;

            // DONTTOUCH: the doc should be loaded for validation even if IgnoreExistingAnnotations = true
            var resourceKey = new ResourceKey(
                target.Type.Assembly,
                competitionMetadata.MetadataResourceName,
                competitionMetadata.UseFullTypeName);

            var xmlAnnotationDoc = _xmlAnnotationsCache.GetOrAdd(
                resourceKey,
                r => XmlAnnotations.TryParseXmlAnnotationDoc(r.Item1, r.Item2, r.Item3, competitionState));

            if (!IgnoreExistingAnnotations && xmlAnnotationDoc != null)
            {
                var parsedLimit = XmlAnnotations.TryParseCompetitionLimit(
                    target,
                    xmlAnnotationDoc,
                    competitionState);

                if (parsedLimit == null)
                {
                    competitionState.WriteMessage(
                        MessageSource.Analyser, MessageSeverity.Warning,
                        $"No XML annotation for {target.MethodTitle} found. Check if the method was renamed.");
                }
                else
                {
                    result = parsedLimit;
                }
            }

            return(result);
        }
Esempio n. 11
0
            // BASEDON: http://stackoverflow.com/questions/36649271/check-that-pdb-file-matches-to-the-source
            public static bool TryGetSourceInfo(
                MethodBase method,
                CompetitionState competitionState,
                out string sourceFileName,
                out int firstCodeLine)
            {
                firstCodeLine  = -1;
                sourceFileName = null;

                var methodSymbols = TryGetMethodSymbols(method, competitionState);

                if (methodSymbols != null)
                {
                    int[] startLines;
                    ISymUnmanagedDocument[] documents;

                    if (TryGetDocsAndLines(methodSymbols, competitionState, out documents, out startLines))
                    {
                        Array.Sort(startLines, documents);
                        var doc = new SymDocument(documents[0]);

                        if (TryValidateFileHash(doc, competitionState))
                        {
                            sourceFileName = doc.Url;
                            firstCodeLine  = startLines[0];
                        }
                    }
                    else
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        competitionState.WriteMessage(
                            MessageSource.Analyser, MessageSeverity.SetupError,
                            $"Method {method.DeclaringType.Name}.{method.Name}, no PDB data available.");
                    }
                }

                return(sourceFileName != null);
            }
Esempio n. 12
0
            private static bool ValidateCore(
                string file,
                ConcurrentDictionary <string, byte[]> fileHashesCache,
                string hashAlgName,
                byte[] expectedChecksum, CompetitionState competitionState)
            {
                var actualChecksum = fileHashesCache.GetOrAdd(file, f => TryGetChecksum(f, hashAlgName));

                if (expectedChecksum.SequenceEqual(actualChecksum))
                {
                    return(true);
                }

                var expected = expectedChecksum.ToHexString();
                var actual   = actualChecksum.ToHexString();

                competitionState.WriteMessage(
                    MessageSource.Analyser, MessageSeverity.SetupError,
                    $"{hashAlgName} checksum validation failed. File '{file}'." +
                    $"{Environment.NewLine}\tActual: 0x{actual}" +
                    $"{Environment.NewLine}\tExpected: 0x{expected}");

                return(false);
            }
Esempio n. 13
0
        public static CompetitionTarget[] TryAnnotateBenchmarkFiles(
            [NotNull] CompetitionTarget[] targetsToAnnotate,
            [NotNull] CompetitionState competitionState)
        {
            Code.NotNull(targetsToAnnotate, nameof(targetsToAnnotate));
            Code.NotNull(competitionState, nameof(competitionState));

            var annotatedTargets = new List <CompetitionTarget>();
            var annContext       = new AnnotateContext();
            var logger           = competitionState.Logger;

            foreach (var targetToAnnotate in targetsToAnnotate)
            {
                var target            = targetToAnnotate.Target;
                var targetMethodTitle = target.MethodTitle;

                logger.WriteLineInfo(
                    $"{LogVerbosePrefix} Method {targetMethodTitle}: updating time limits {targetToAnnotate}.");

                // DONTTOUCH: the source should be loaded for checksum validation even if target uses resource annotation.
                string fileName;
                int    firstCodeLine;
                bool   hasSource = SymbolHelpers.TryGetSourceInfo(target.Method, competitionState, out fileName, out firstCodeLine);

                if (!hasSource)
                {
                    continue;
                }

                var competitionMetadata = targetToAnnotate.CompetitionMetadata;
                if (competitionMetadata != null)
                {
                    var resourceFileName = GetResourceFileName(fileName, competitionMetadata);

                    logger.WriteLineInfo(
                        $"{LogVerbosePrefix} Method {targetMethodTitle}: annotating resource file '{resourceFileName}'.");
                    var annotated = TryFixBenchmarkXmlAnnotation(annContext, resourceFileName, targetToAnnotate, competitionState);
                    if (!annotated)
                    {
                        competitionState.WriteMessage(
                            MessageSource.Analyser, MessageSeverity.Warning,
                            $"Method {targetMethodTitle}: could not annotate resource file '{resourceFileName}'.", null);
                        continue;
                    }
                }
                else
                {
                    logger.WriteLineInfo(
                        $"{LogVerbosePrefix} Method {targetMethodTitle}: annotating file '{fileName}', line {firstCodeLine}.");
                    var annotated = TryFixBenchmarkAttribute(annContext, fileName, firstCodeLine, targetToAnnotate, competitionState);
                    if (!annotated)
                    {
                        competitionState.WriteMessage(
                            MessageSource.Analyser, MessageSeverity.Warning,
                            $"Method {targetMethodTitle}: could not annotate source file '{fileName}'.");
                        continue;
                    }
                }

                logger.WriteLineInfo(
                    $"{LogImportantInfoPrefix} Method {targetMethodTitle} updated time limits: {targetToAnnotate}.");
                annotatedTargets.Add(targetToAnnotate);
            }

            annContext.Save();
            return(annotatedTargets.ToArray());
        }
Esempio n. 14
0
        public static XDocument[] TryParseXmlAnnotationDocsFromLog(
            [NotNull] string logUri,
            [NotNull] CompetitionState competitionState)
        {
            Code.NotNullNorEmpty(logUri, nameof(logUri));
            Code.NotNull(competitionState, nameof(competitionState));

            var result = new List <XDocument>();

            var logger = competitionState.Logger;

            logger.WriteLineInfo($"{LogVerbosePrefix} Downloading '{logUri}'.");

            using (var reader = BenchmarkHelpers.TryGetTextFromUri(logUri, TimeSpan.FromSeconds(15)))
            {
                if (reader == null)
                {
                    competitionState.WriteMessage(
                        MessageSource.Analyser, MessageSeverity.SetupError,
                        $"Could not load log content from '{logUri}'.");
                    return(Array <XDocument> .Empty);
                }

                logger.WriteLineInfo($"{LogVerbosePrefix} Downloaded '{logUri}'.");

                var    buffer = new StringBuilder();
                int    lineNumber = 0, xmlStartLineNumber = -1;
                string logLine;
                while ((logLine = reader.ReadLine()) != null)
                {
                    lineNumber++;

                    if (logLine.StartsWith(LogAnnotationStart, StringComparison.OrdinalIgnoreCase))
                    {
                        xmlStartLineNumber = lineNumber;
                    }
                    else if (logLine.StartsWith(LogAnnotationEnd, StringComparison.OrdinalIgnoreCase))
                    {
                        if (buffer.Length > 0)
                        {
                            var xmlAnnotationDoc = TryParseXmlAnnotationDocFromLogCore(
                                buffer.ToString(), competitionState, logUri, xmlStartLineNumber);
                            if (xmlAnnotationDoc != null)
                            {
                                result.Add(xmlAnnotationDoc);
                            }
                        }
                        buffer.Length = 0;

                        xmlStartLineNumber = -1;
                    }
                    else if (xmlStartLineNumber >= 0)
                    {
                        buffer.Append(logLine);
                    }
                }

                if (buffer.Length > 0)
                {
                    var xmlAnnotationDoc = TryParseXmlAnnotationDocFromLogCore(
                        buffer.ToString(), competitionState, logUri, xmlStartLineNumber);
                    if (xmlAnnotationDoc != null)
                    {
                        result.Add(xmlAnnotationDoc);
                    }
                }
            }

            return(result.ToArray());
        }