private static void CheckMembers(ResultAnalysis analysis) { var summary = analysis.Summary; // No duplicate names var targets = summary.GetBenchmarkTargets(); var duplicateTargets = GetDuplicates( targets, t => t.Method.Name, t => $"\r\n\t\t {t.Method.DeclaringType}.{t.Method.Name}()"); if (duplicateTargets.NotNullNorEmpty()) { analysis.WriteSetupErrorMessage( $"There are multiple methods with same name: {duplicateTargets.Join(",\r\n\t\t")}.", "Rename methods to avoid duplicates."); } // No conflict on attributes var targetMethodsWithAttributes = targets .SelectMany(GetInvokedMethods) .Distinct() .SelectMany( m => m.GetCustomAttributes(true) .Select(a => (method: m, attributeType: a.GetType(), baseAttribute: _knownUniqueMemberLevelAttributes.FirstOrDefault(ka => ka.IsInstanceOfType(a)), target: (a as TargetedAttribute)?.Target)) .Where(t => t.baseAttribute != null)) .ToArray(); var conflictingAttributes = GetDuplicates( targetMethodsWithAttributes, t => $"{t.method.DeclaringType}.{t.method.Name}({t.target})", t => $"\r\n\t\t {t.attributeType.FullName}"); if (conflictingAttributes.NotNullNorEmpty()) { analysis.WriteSetupErrorMessage( $"There are conflicting attributes: {conflictingAttributes.Join(",\r\n\t\t")}.", "There can be only one."); } // No multiple methods for an attribute var conflictingMethods = GetDuplicates( targetMethodsWithAttributes.Where(t => _knownUniqueTypeLevelAttributes.Contains(t.baseAttribute)), t => $"{t.baseAttribute.FullName}({t.target})", t => $"\r\n\t\t {t.method.DeclaringType}.{t.method.Name}() ({t.attributeType.FullName})"); if (conflictingMethods.NotNullNorEmpty()) { analysis.WriteSetupErrorMessage( $"There are conflicting methods: {conflictingMethods.Join(",\r\n\t\t")}.", "Leave only one method for each attribute."); } }
private static bool CheckSetup(ResultAnalysis analysis) { var summary = analysis.Summary; // DONTTOUCH: DO NOT add return into if clauses. // All conditions should be checked if (summary.HasCriticalValidationErrors) { analysis.WriteExecutionErrorMessage("Summary has validation errors."); } if (!summary.HasCriticalValidationErrors && summary.Benchmarks.IsNullOrEmpty()) { analysis.WriteSetupErrorMessage( "Nothing to check as there is no methods in benchmark.", $"Apply one of {nameof(CompetitionBenchmarkAttribute)}, {nameof(CompetitionBaselineAttribute)} or {nameof(BenchmarkAttribute)} to the benchmark methods."); } if (summary.Config.GetJobs().Skip(1).Any()) { analysis.WriteSetupErrorMessage( "Benchmark configuration includes multiple jobs. " + "This is not supported as there's no way to store metric annotations individually per each job.", "Ensure that the config contains only one job."); } if (summary.Benchmarks.Select(b => b.Parameters).Distinct().Skip(1).Any()) { analysis.WriteInfoMessage( "Benchmark configuration includes multiple parameters. " + "Note that results for each parameter set will be merged."); } CheckMembers(analysis); CheckMetrics(analysis); return(analysis.SafeToContinue); }
/// <summary>Dumps validation messages.</summary> /// <param name="summary">Summary for the run.</param> /// <returns>Enumerable with warnings for the benchmarks.</returns> public IEnumerable <Conclusion> Analyse([NotNull] Summary summary) { var analysis = new ResultAnalysis(Id, summary, MessageSource.Validator); foreach (var validationError in summary.ValidationErrors) { var message = validationError.Benchmark == null ? validationError.Message : $"Benchmark {validationError.Benchmark.DisplayInfo}:{Environment.NewLine}\t{validationError.Message}"; if (validationError.IsCritical) { analysis.WriteSetupErrorMessage(message); } else { analysis.WriteWarningMessage(message); } } return(analysis.Conclusions); }