Skip to content

Commit

Permalink
#408 added baseline IT for Maven and updated manual
Browse files Browse the repository at this point in the history
  • Loading branch information
DirkMahler committed Jul 13, 2024
1 parent e1804ac commit f459788
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.buschmais.jqassistant.core.analysis.api;

import com.buschmais.jqassistant.core.analysis.api.configuration.Analyze;
import com.buschmais.jqassistant.core.rule.api.model.RuleException;
import com.buschmais.jqassistant.core.rule.api.model.RuleSelection;
import com.buschmais.jqassistant.core.rule.api.model.RuleSet;
Expand All @@ -10,13 +9,6 @@
*/
public interface Analyzer {

/**
* Return the {@link Analyze} configuration.
*
* @return The {@link Analyze} configuration.
*/
Analyze getConfiguration();

/**
* Executes the given rule set.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,19 @@ private Boolean isExistingResult(ExecutableRule<?> executableRule, Row row, List
Baseline.RuleBaseline oldRuleBaseline = ruleBaseline.get(ruleId);
if (oldRuleBaseline != null && oldRuleBaseline.getRows()
.containsKey(rowKey)) {
add(ruleId, rowKey, columns);
add(ruleId, rowKey, columns, rows);
return true;
}
return false;
})
.orElseGet(() -> {
add(ruleId, rowKey, columns);
add(ruleId, rowKey, columns, rows);
return false;
});
}

private void add(String constraintId, String rowKey, Map<String, Column<?>> columns) {
Baseline.RuleBaseline newRuleBaseline = newBaseline.getConstraints()
private void add(String constraintId, String rowKey, Map<String, Column<?>> columns, Function<Baseline, SortedMap<String, Baseline.RuleBaseline>> rows) {
Baseline.RuleBaseline newRuleBaseline = rows.apply(newBaseline)
.computeIfAbsent(constraintId, key -> new Baseline.RuleBaseline());
TreeMap<String, String> row = new TreeMap<>();
columns.entrySet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ public class AnalyzerImpl implements Analyzer {

private final Analyze configuration;

private final AnalyzerContext analyzerContext;
private final ClassLoader classLoader;

private final Store store;

private final Map<String, Collection<RuleInterpreterPlugin>> ruleInterpreterPlugins;

private final BaselineManager baselineManager;

private final ReportPlugin reportPlugin;

/**
Expand All @@ -46,22 +50,22 @@ public class AnalyzerImpl implements Analyzer {
* The report writer.
*/
public AnalyzerImpl(Analyze configuration, ClassLoader classLoader, Store store, Map<String, Collection<RuleInterpreterPlugin>> ruleInterpreterPlugins,
BaselineManager baselineManager, ReportPlugin reportPlugin) throws RuleException {
BaselineManager baselineManager, ReportPlugin reportPlugin) {
this.configuration = configuration;
this.analyzerContext = new AnalyzerContextImpl(configuration, classLoader, store, baselineManager);
this.classLoader = classLoader;
this.store = store;
this.ruleInterpreterPlugins = ruleInterpreterPlugins;
this.baselineManager = baselineManager;
this.reportPlugin = reportPlugin;
}

@Override
public Analyze getConfiguration() {
return configuration;
}

@Override
public void execute(RuleSet ruleSet, RuleSelection ruleSelection) throws RuleException {
AnalyzerContext analyzerContext = new AnalyzerContextImpl(configuration, classLoader, store, baselineManager);
baselineManager.start();
AnalyzerRuleVisitor visitor = new AnalyzerRuleVisitor(configuration, analyzerContext, ruleInterpreterPlugins, reportPlugin);
RuleSetExecutor<Result.Status> executor = new RuleSetExecutor<>(visitor, configuration.rule());
executor.execute(ruleSet, ruleSelection);
baselineManager.stop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public class AnalyzerRuleVisitor extends AbstractRuleVisitor<Result.Status> {

private final Analyze configuration;
private final AnalyzerContext analyzerContext;
private final ReportPlugin reportPlugin;
private final Map<String, Collection<RuleInterpreterPlugin>> ruleInterpreterPlugins;
private final ReportPlugin reportPlugin;
private final Store store;
private final RuleRepository ruleRepository;
private final Deque<RuleGroupTemplate> ruleGroups = new ArrayDeque<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Stream;

import com.buschmais.jqassistant.core.report.api.model.Column;
Expand Down Expand Up @@ -93,7 +92,7 @@ void noBaselineWithNewConstraintViolation(ExecutableRule<?> executableRule) {
assertThat(baselineManager.isExisting(executableRule, row)).isFalse();
baselineManager.stop();

verifyNewBaseline(executableRule, baseline -> baseline.getConstraints(), "1");
verifyNewBaseline(executableRule, "1");
}

@ParameterizedTest
Expand All @@ -114,7 +113,7 @@ void existingBaselineWithExistingConstraintViolation(ExecutableRule<?> executabl
assertThat(baselineManager.isExisting(executableRule, row)).isTrue();
baselineManager.stop();

verifyNewBaseline(executableRule, baseline -> baseline.getConstraints(), "1");
verifyNewBaseline(executableRule, "1");
}

@ParameterizedTest
Expand Down Expand Up @@ -142,7 +141,7 @@ void existingBaselineWithNewConstraintViolation(ExecutableRule<?> executableRule
assertThat(baselineManager.isExisting(executableRule, newRow)).isFalse();
baselineManager.stop();

verifyNewBaseline(executableRule, baseline -> baseline.getConstraints(), "1");
verifyNewBaseline(executableRule, "1");
}

@ParameterizedTest
Expand All @@ -163,7 +162,7 @@ void existingBaselineWithRemovedConstraintViolation(ExecutableRule<?> executable
assertThat(baselineManager.isExisting(executableRule, row)).isTrue();
baselineManager.stop();

verifyNewBaseline(executableRule, baseline -> baseline.getConstraints(), "1");
verifyNewBaseline(executableRule, "1");
}

@Test
Expand Down Expand Up @@ -245,11 +244,10 @@ private static Baseline createOldBaseline(ExecutableRule<?> rule, String... rowK
return oldBaseline;
}

private void verifyNewBaseline(ExecutableRule<?> executableRule, Function<Baseline, SortedMap<String, Baseline.RuleBaseline>> rulebaseLinesFunction,
String... expectedRowKeys) {
private void verifyNewBaseline(ExecutableRule<?> executableRule, String... expectedRowKeys) {
verify(baselineRepository).write(baselineArgumentCaptor.capture());
Baseline newBaseline = baselineArgumentCaptor.getValue();
SortedMap<String, Baseline.RuleBaseline> ruleBaselines = rulebaseLinesFunction.apply(newBaseline);
SortedMap<String, Baseline.RuleBaseline> ruleBaselines = executableRule instanceof Concept ? newBaseline.getConcepts() : newBaseline.getConstraints();
assertThat(ruleBaselines).hasSize(1)
.containsKey(executableRule.getId());
Baseline.RuleBaseline ruleBaseline = ruleBaselines.get(executableRule.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
import com.buschmais.jqassistant.core.rule.impl.SourceExecutable;
import com.buschmais.jqassistant.core.shared.xml.JAXBUnmarshaller;

import lombok.extern.slf4j.Slf4j;
import org.jqassistant.schema.rule.v2.*;

import static com.buschmais.jqassistant.core.rule.impl.reader.IndentHelper.removeIndent;
import static java.util.stream.Collectors.toSet;

/**
* A {@link RuleParserPlugin} implementation.
*/
@Slf4j
public class XmlRuleParserPlugin extends AbstractRuleParserPlugin {

private static final String NAMESPACE_RULE = "http://schema.jqassistant.org/rule/v2.2";
Expand All @@ -38,7 +41,9 @@ public void initialize() {

@Override
public boolean accepts(RuleSource ruleSource) {
return ruleSource.getId().toLowerCase().endsWith(".xml");
return ruleSource.getId()
.toLowerCase()
.endsWith(".xml");
}

@Override
Expand All @@ -51,7 +56,7 @@ public void doParse(RuleSource ruleSource, RuleSetBuilder ruleSetBuilder) throws
* Read rules from XML documents.
*
* @param ruleSource
* The available sources.
* The available sources.
* @return The list of found rules.
*/
private List<JqassistantRules> readXmlSource(RuleSource ruleSource) {
Expand All @@ -60,7 +65,9 @@ private List<JqassistantRules> readXmlSource(RuleSource ruleSource) {
JqassistantRules jqassistantRules = jaxbUnmarshaller.unmarshal(inputStream);
rules.add(jqassistantRules);
} catch (IOException e) {
throw new IllegalArgumentException("Cannot read rules from '" + ruleSource.getId() + "'.", e);
// TODO remove workaround, rule sources should be valid
// throw new IllegalArgumentException("Cannot read rules from '" + ruleSource.getId() + "'.", e);
log.warn("Cannot read rules from '{}'.", ruleSource);
}
return rules;
}
Expand All @@ -69,9 +76,9 @@ private List<JqassistantRules> readXmlSource(RuleSource ruleSource) {
* Converts a list of {@link JqassistantRules} to a rule set.
*
* @param rules
* The {@link JqassistantRules}.
* The {@link JqassistantRules}.
* @throws RuleException
* If rules are not consistent.
* If rules are not consistent.
*/
private void convert(List<JqassistantRules> rules, RuleSource ruleSource, RuleSetBuilder builder) throws RuleException {
for (JqassistantRules rule : rules) {
Expand Down Expand Up @@ -107,19 +114,21 @@ private Group createGroup(String id, RuleSource ruleSource, GroupType referencab
.providedConcepts(providedConcepts)
.constraints(includeConstraints)
.groups(includeGroups)
.build();
.build();
}

private Concept createConcept(String id, RuleSource ruleSource, ConceptType conceptType) throws RuleException {
String description = removeIndent(conceptType.getDescription());
Executable<?> executable = createExecutable(conceptType, conceptType.getSource(), conceptType.getCypher(), conceptType.getScript());
Executable<?> executable = createExecutable(conceptType.getSource(), conceptType.getCypher(), conceptType.getScript());
Map<String, Parameter> parameters = getRequiredParameters(conceptType.getRequiresParameter());
SeverityEnumType severityType = conceptType.getSeverity();
Severity severity = getSeverity(severityType, this::getDefaultConceptSeverity);
List<OptionalReferenceType> requiresConcept = conceptType.getRequiresConcept();
Map<String, Boolean> requiresConcepts = getRequiresConcepts(requiresConcept);
List<ReferenceType> providesConcept = conceptType.getProvidesConcept();
Set<String> providesConcepts = providesConcept.stream().map(ReferenceType::getRefId).collect(toSet());
Set<String> providesConcepts = providesConcept.stream()
.map(ReferenceType::getRefId)
.collect(toSet());
String deprecated = conceptType.getDeprecated();
Verification verification = getVerification(conceptType.getVerify());
Report report = getReport(conceptType.getReport());
Expand All @@ -139,7 +148,7 @@ private Concept createConcept(String id, RuleSource ruleSource, ConceptType conc
}

private Constraint createConstraint(String id, RuleSource ruleSource, ConstraintType constraintType) throws RuleException {
Executable<?> executable = createExecutable(constraintType, constraintType.getSource(), constraintType.getCypher(), constraintType.getScript());
Executable<?> executable = createExecutable(constraintType.getSource(), constraintType.getCypher(), constraintType.getScript());
String description = removeIndent(constraintType.getDescription());
Map<String, Parameter> parameters = getRequiredParameters(constraintType.getRequiresParameter());
SeverityEnumType severityType = constraintType.getSeverity();
Expand All @@ -163,16 +172,18 @@ private Constraint createConstraint(String id, RuleSource ruleSource, Constraint
.build();
}

private Executable<?> createExecutable(SeverityRuleType severityRuleType, SourceType source, CypherType cypherType, SourceType scriptType) throws RuleException {
private Executable<?> createExecutable(SourceType source, CypherType cypherType, SourceType scriptType) {
if (source != null) {
return new SourceExecutable<>(source.getLanguage().toLowerCase(), source.getValue(), String.class);
return new SourceExecutable<>(source.getLanguage()
.toLowerCase(), source.getValue(), String.class);
}
// for compatibility
if (cypherType != null) {
return new CypherExecutable(cypherType.getValue());
}
if (scriptType != null) {
return new ScriptExecutable(scriptType.getLanguage().toLowerCase(), scriptType.getValue());
return new ScriptExecutable(scriptType.getLanguage()
.toLowerCase(), scriptType.getValue());
}
return null;
}
Expand All @@ -185,10 +196,16 @@ private Verification getVerification(VerificationType verificationType) throws R
RowCountVerificationType rowCountVerificationType = verificationType.getRowCount();
AggregationVerificationType aggregationVerificationType = verificationType.getAggregation();
if (aggregationVerificationType != null) {
return AggregationVerification.builder().column(aggregationVerificationType.getColumn()).min(aggregationVerificationType.getMin())
.max(aggregationVerificationType.getMax()).build();
return AggregationVerification.builder()
.column(aggregationVerificationType.getColumn())
.min(aggregationVerificationType.getMin())
.max(aggregationVerificationType.getMax())
.build();
} else if (rowCountVerificationType != null) {
return RowCountVerification.builder().min(rowCountVerificationType.getMin()).max(rowCountVerificationType.getMax()).build();
return RowCountVerification.builder()
.min(rowCountVerificationType.getMin())
.max(rowCountVerificationType.getMax())
.build();
} else {
throw new RuleException("Unsupported verification " + verificationType);
}
Expand All @@ -200,7 +217,7 @@ private Verification getVerification(VerificationType verificationType) throws R
* Read the report definition.
*
* @param reportType
* The report type.
* The report type.
* @return The report definition.
*/
private Report getReport(ReportType reportType) {
Expand All @@ -214,7 +231,9 @@ private Report getReport(ReportType reportType) {
properties.setProperty(propertyType.getName(), propertyType.getValue());
}
}
Report.ReportBuilder reportBuilder = Report.builder().primaryColumn(primaryColumn).properties(properties);
Report.ReportBuilder reportBuilder = Report.builder()
.primaryColumn(primaryColumn)
.properties(properties);
if (type != null) {
reportBuilder.selectedTypes(Report.selectTypes(type));
}
Expand Down
2 changes: 1 addition & 1 deletion core/schemata/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<fileset>
<directory>${project.basedir}/src/main/resources/META-INF/baseline/xsd</directory>
<includes>
<include>jqassistant-baseline-v2.3.xsd</include>
<include>jqassistant-baseline-v2.4.xsd</include>
</includes>
</fileset>
</schema>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://schema.jqassistant.org/baseline/v2.3"
targetNamespace="http://schema.jqassistant.org/baseline/v2.3"
xmlns:tns="http://schema.jqassistant.org/baseline/v2.4"
targetNamespace="http://schema.jqassistant.org/baseline/v2.4"
elementFormDefault="qualified">

<xs:element name="jqassistant-baseline">
Expand Down
25 changes: 25 additions & 0 deletions manual/src/main/asciidoc/include/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,31 @@ jqassistant:
# -Djqassistant.analyze.rule.default-group-severity: INFO|MINOR|MAJOR|CRITICAL|BLOCKER
default-group-severity:
# The baseline configuration
baseline:
# Enables baseline management for concept and constraint results.
#
# -Djqassistant.analyze.baseline.enabled: true|false
enabled: false
# The file name for storing the baseline.
#
# -Djqassistant.analyze.baseline.file
file: jqassistant/jqassistant-baseline.xml
# The concepts to be managed in the baseline (default: none)
#
# -Djqassistant.analyze.baseline-include.concepts[0]
include.concepts:
# - my-concept
# The constraints to be managed in the baseline (default: all)
#
# -Djqassistant.analyze.baseline.include-constraints[0]
include-constraints:
- "*"
# The report configuration
report:
Expand Down
Loading

0 comments on commit f459788

Please sign in to comment.