Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
#106 added BaselineRepository
Browse files Browse the repository at this point in the history
  • Loading branch information
DirkMahler committed Jul 5, 2024
1 parent 6d93442 commit 188f1d1
Show file tree
Hide file tree
Showing 12 changed files with 479 additions and 103 deletions.
2 changes: 1 addition & 1 deletion analysis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
* <li>A baseline exists but does not yet contain the {@link Row}.</li>
* </ul>
* <p>
* Only {@link Row}s that have been validated using {@link #isNew(ExecutableRule, Row)} (Constraint, Row)} are copied to the new baseline.
* This means that between two executions resolved {@link Constraint} violations are removed from the baseline.
* Only {@link Row}s that have been validated using {@link #isNew(ExecutableRule, Row)} ({@link ExecutableRule}, Row)} are copied to the new baseline.
* <p>
*/
@RequiredArgsConstructor
public class BaselineManager {

private final com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration;

private final Optional<Baseline> optionalOldBaseline;

private final Baseline newBaseline = new Baseline();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.buschmais.jqassistant.core.analysis.api.baseline;

import java.io.*;
import java.util.*;

import com.buschmais.jqassistant.core.shared.xml.JAXBHelper;

import lombok.RequiredArgsConstructor;
import org.jqassistant.schema.baseline.v2.ColumnType;
import org.jqassistant.schema.baseline.v2.JqassistantBaseline;
import org.jqassistant.schema.baseline.v2.RowType;
import org.jqassistant.schema.baseline.v2.RuleType;

import static java.util.Optional.empty;
import static java.util.Optional.of;

@RequiredArgsConstructor
public class BaselineRepository {

private static final JAXBHelper<JqassistantBaseline> JAXB_HELPER = new JAXBHelper<>(JqassistantBaseline.class);

private final com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration;

private final File ruleDirectory;

public Optional<Baseline> read() {
File baselineFile = getFile();
if (baselineFile.exists()) {
return of(read(baselineFile));
}
return empty();
}

public void write(Baseline baseline) {
write(baseline, getFile());
}

private File getFile() {
return configuration.file()
.map(File::new)
.orElse(new File(ruleDirectory, "jqassistant-baseline.xml"));
}

private static Baseline read(File baselineFile) {
try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(baselineFile))) {
return toBaseline(JAXB_HELPER.unmarshal(inputStream));
} catch (IOException e) {
throw new IllegalStateException("Unable to read baseline file " + baselineFile, e);
}
}

private static Baseline toBaseline(JqassistantBaseline jqassistantBaseline) {
Baseline baseline = new Baseline();
toBaseline(jqassistantBaseline.getConstraint(), baseline.getConstraints());
toBaseline(jqassistantBaseline.getConcept(), baseline.getConcepts());
return baseline;
}

private static void toBaseline(List<RuleType> ruleTypes, SortedMap<String, Baseline.RuleBaseline> ruleBaselines) {
for (RuleType ruleType : ruleTypes) {
Baseline.RuleBaseline ruleBaseline = new Baseline.RuleBaseline();
for (RowType rowType : ruleType.getRow()) {
SortedMap<String, String> columns = new TreeMap<>();
for (ColumnType columnType : rowType.getColumn()) {
columns.put(columnType.getName(), columnType.getValue());
}
ruleBaseline.getRows()
.put(rowType.getKey(), columns);
}
ruleBaselines.put(ruleType.getId(), ruleBaseline);
}
}

private static void write(Baseline baseline, File baselinefile) {
JqassistantBaseline jqassistantBaseline = fromBaseline(baseline);
try {
JAXB_HELPER.marshal(jqassistantBaseline, new FileOutputStream(baselinefile));
} catch (IOException e) {
throw new IllegalStateException("Unable to write baseline file " + baselinefile, e);
}
}

private static JqassistantBaseline fromBaseline(Baseline baseline) {
JqassistantBaseline jqassistantBaseline = new JqassistantBaseline();
fromBaseline(baseline.getConstraints(), jqassistantBaseline.getConstraint());
fromBaseline(baseline.getConcepts(), jqassistantBaseline.getConcept());
return jqassistantBaseline;
}

private static void fromBaseline(SortedMap<String, Baseline.RuleBaseline> ruleBaselines, List<RuleType> ruleTypes) {
for (Map.Entry<String, Baseline.RuleBaseline> ruleBaselineEntry : ruleBaselines.entrySet()) {
String ruleId = ruleBaselineEntry.getKey();
Baseline.RuleBaseline ruleBaseline = ruleBaselineEntry.getValue();
RuleType ruleType = new RuleType();
ruleType.setId(ruleId);
for (Map.Entry<String, SortedMap<String, String>> rowEntry : ruleBaseline.getRows()
.entrySet()) {
String rowKey = rowEntry.getKey();
SortedMap<String, String> columns = rowEntry.getValue();
RowType rowType = new RowType();
rowType.setKey(rowKey);
for (Map.Entry<String, String> columnEntry : columns.entrySet()) {
ColumnType columnType = new ColumnType();
columnType.setName(columnEntry.getKey());
columnType.setValue(columnEntry.getValue());
rowType.getColumn()
.add(columnType);
}
ruleType.getRow()
.add(rowType);
ruleTypes.add(ruleType);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ public interface Analyze {
@Description("The rule configuration.")
Rule rule();

/**
* The {@link Baseline} configuration.
*
* @return The {@link Baseline} configuration.
*/
@Description("The baseline configuration.")
Baseline baseline();

/**
* The {@link Report} configuration.
*
Expand All @@ -41,6 +49,7 @@ public interface Analyze {
Optional<List<String>> constraints();

String EXCLUDE_CONSTRAINTS = "exclude-constraints";

@Description("The constraints to be excluded.")
Optional<List<String>> excludeConstraints();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.buschmais.jqassistant.core.analysis.api.configuration;

import java.util.List;
import java.util.Optional;

import com.buschmais.jqassistant.core.shared.annotation.Description;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;

@ConfigMapping(prefix = "jqassistant.analyze.baseline")
public interface Baseline {

@WithDefault("false")
boolean enabled();

String FILE = "file";

@Description("The name of the file for reading and writing the baseline.")
Optional<String> file();

String INCLUDE_CONCEPTS = "include-concepts";

@Description("The concepts to be included.")
Optional<List<String>> includeConcepts();

String INCLUDE_CONSTRAINTS = "include-constraints";

@Description("The constraints to be included.")
@WithDefault("*")
List<String> includeConstraints();

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
import com.buschmais.jqassistant.core.rule.api.model.Constraint;
import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule;

import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(MockitoExtension.class)
class BaselineManagerTest {

private static Stream<Arguments> rules() {
Expand All @@ -29,6 +33,9 @@ private static Stream<Arguments> rules() {
.build()));
}

@Mock
private com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration;

@ParameterizedTest
@MethodSource("rules")
void noBaselineWithNewConstraintViolation(ExecutableRule<?> executableRule) {
Expand All @@ -38,7 +45,7 @@ void noBaselineWithNewConstraintViolation(ExecutableRule<?> executableRule) {
.label("1")
.build()))
.build();
BaselineManager baselineManager = new BaselineManager(empty());
BaselineManager baselineManager = new BaselineManager(configuration,empty());

assertThat(baselineManager.isNew(executableRule, row)).isTrue();

Expand All @@ -56,7 +63,7 @@ void existingBaselineWithExistingConstraintViolation(ExecutableRule<?> executabl
.label("1")
.build()))
.build();
BaselineManager baselineManager = new BaselineManager(of(oldBaseline));
BaselineManager baselineManager = new BaselineManager(configuration, of(oldBaseline));

assertThat(baselineManager.isNew(executableRule, row)).isFalse();

Expand All @@ -80,7 +87,7 @@ void existingBaselineWithNewConstraintViolation(ExecutableRule<?> executableRule
.label("2")
.build()))
.build();
BaselineManager baselineManager = new BaselineManager(of(oldBaseline));
BaselineManager baselineManager = new BaselineManager(configuration, of(oldBaseline));

assertThat(baselineManager.isNew(executableRule, oldRow)).isFalse();
assertThat(baselineManager.isNew(executableRule, newRow)).isTrue();
Expand All @@ -99,7 +106,7 @@ void existingBaselineWithRemovedConstraintViolation(ExecutableRule<?> executable
.label("1")
.build()))
.build();
BaselineManager baselineManager = new BaselineManager(of(oldBaseline));
BaselineManager baselineManager = new BaselineManager(configuration, of(oldBaseline));

assertThat(baselineManager.isNew(executableRule, row)).isFalse();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.buschmais.jqassistant.core.analysis.api.baseline;

import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.SortedMap;

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Optional.of;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;

@ExtendWith(MockitoExtension.class)
class BaselineRepositoryTest {

private static final File RULE_DIRECTORY = new File("target/test-classes");
private static final File BASELINE_FILE = new File(RULE_DIRECTORY, "jqassistant-baseline.xml");
public static final File UPDATED_BASELINE_FILE = new File(RULE_DIRECTORY, "jqassistant-baseline.updated.xml");

@Mock
private com.buschmais.jqassistant.core.analysis.api.configuration.Baseline configuration;

@Test
void readNonExisting() {
doReturn(of("non-existing-baseline.xml")).when(configuration)
.file();
BaselineRepository baselineRepository = new BaselineRepository(configuration, RULE_DIRECTORY);

assertThat(baselineRepository.read()).isNotPresent();
}

@Test
void readFromConfiguredFile() {
doReturn(of(BASELINE_FILE.getAbsolutePath())).when(configuration)
.file();

BaselineRepository baselineRepository = new BaselineRepository(configuration, new File("."));

Optional<Baseline> optionalBaseline = baselineRepository.read();
verify(optionalBaseline);
}

@Test
void readFromRuleDirectory() {
BaselineRepository baselineRepository = new BaselineRepository(configuration, RULE_DIRECTORY);

Optional<Baseline> optionalBaseline = baselineRepository.read();
verify(optionalBaseline);
}

@Test
void update() throws IOException {
FileUtils.copyFile(BASELINE_FILE, UPDATED_BASELINE_FILE);
doReturn(of(UPDATED_BASELINE_FILE.getAbsolutePath())).when(configuration)
.file();
BaselineRepository baselineRepository = new BaselineRepository(configuration, new File("."));

Optional<Baseline> optionalBaseline = baselineRepository.read();
assertThat(optionalBaseline).isPresent();
baselineRepository.write(optionalBaseline.get());

assertThat(readFileToString(UPDATED_BASELINE_FILE, UTF_8)).isEqualTo(readFileToString(BASELINE_FILE, UTF_8));
}

private static void verify(Optional<Baseline> optionalBaseline) {
assertThat(optionalBaseline).isPresent();
Baseline baseline = optionalBaseline.get();
verify(baseline.getConcepts(), "test-concept");
verify(baseline.getConstraints(), "test-constraint");
}

private static void verify(SortedMap<String, Baseline.RuleBaseline> ruleBaselines, String ruleId) {
assertThat(ruleBaselines).hasSize(1);
Baseline.RuleBaseline ruleBaseline = ruleBaselines.get(ruleId);
assertThat(ruleBaseline).isNotNull();
SortedMap<String, SortedMap<String, String>> rows = ruleBaseline.getRows();
assertThat(rows).hasSize(1);
SortedMap<String, String> row = rows.get("1");
assertThat(row).isNotNull()
.hasSize(2)
.containsEntry("c1", "value 1")
.containsEntry("c2", "value 2");
}

}
15 changes: 15 additions & 0 deletions analysis/src/test/resources/jqassistant-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jqassistant-baseline xmlns="http://schema.jqassistant.org/baseline/v2.3">
<constraint id="test-constraint">
<row key="1">
<column name="c1">value 1</column>
<column name="c2">value 2</column>
</row>
</constraint>
<concept id="test-concept">
<row key="1">
<column name="c1">value 1</column>
<column name="c2">value 2</column>
</row>
</concept>
</jqassistant-baseline>
Loading

0 comments on commit 188f1d1

Please sign in to comment.