Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/source comparator passed test code compare #413

Merged
merged 14 commits into from
Feb 15, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ All notable changes to AET will be documented in this file.
- [PR-430](https://github.com/Cognifide/aet/pull/430) Upgraded HTML codesniffer to latest release (3.2.0)

- [PR-385](https://github.com/Cognifide/aet/pull/385) Fixed ChefDK and vagrant-berkshelf versions
- [PR-413](https://github.com/Cognifide/aet/pull/413) Feature/source comparator passed test code compare ([#369](https://github.com/Cognifide/aet/issues/369))

## Version 3.1.0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* AET
*
* Copyright (C) 2018 Cognifide Limited
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.cognifide.aet.job.common.comparators.source;

import com.cognifide.aet.job.common.comparators.source.visitors.ContentVisitor;
import com.cognifide.aet.job.common.comparators.source.visitors.MarkupVisitor;
import com.cognifide.aet.job.common.comparators.source.visitors.NodeTraversor;
import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

class CodeFormatter {
ernestosiak marked this conversation as resolved.
Show resolved Hide resolved

private static final Pattern EMPTY_LINE_PATTERN = Pattern.compile("^[\\s]*$");

private static final String NEWLINE = "\\r?\\n";

String format(String code, SourceCompareType sourceCompareType) {
String result;
switch (sourceCompareType) {
case MARKUP:
result = formatCodeMarkup(code);
break;
case CONTENT:
result = formatCodeContent(code);
break;
case ALLFORMATTED:
result = formatCodeAllFormatted(code);
break;
default:
result = code;
break;
}
return result;
}

private String formatCodeMarkup(String code) {
Document doc = Jsoup.parse(code);
NodeTraversor traversor = new NodeTraversor(new MarkupVisitor());
traversor.traverse(doc);
return doc.html();
}

private String formatCodeContent(String code) {
Document doc = Jsoup.parse(code);
ContentVisitor visitor = new ContentVisitor();
NodeTraversor traversor = new NodeTraversor(visitor);
traversor.traverse(doc);
return visitor.getFormattedText();
}

private String formatCodeAllFormatted(String code) {
Document doc = Jsoup.parse(code);
return removeEmptyLines(doc.outerHtml());
}

// package scoped for unit test
String removeEmptyLines(String source) {
String[] lines = source.split(NEWLINE);
return Arrays
.stream(lines)
.filter(line -> !EMPTY_LINE_PATTERN.matcher(line).matches())
.collect(Collectors.joining("\n"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,164 +16,107 @@
package com.cognifide.aet.job.common.comparators.source;

import com.cognifide.aet.communication.api.metadata.ComparatorStepResult;
import com.cognifide.aet.communication.api.metadata.ComparatorStepResult.Status;
import com.cognifide.aet.job.api.comparator.ComparatorJob;
import com.cognifide.aet.job.api.comparator.ComparatorProperties;
import com.cognifide.aet.job.api.datafilter.DataFilterJob;
import com.cognifide.aet.job.api.exceptions.ParametersException;
import com.cognifide.aet.job.api.exceptions.ProcessingException;
import com.cognifide.aet.job.common.comparators.source.diff.DiffParser;
import com.cognifide.aet.job.common.comparators.source.diff.ResultDelta;
import com.cognifide.aet.job.common.comparators.source.visitors.ContentVisitor;
import com.cognifide.aet.job.common.comparators.source.visitors.MarkupVisitor;
import com.cognifide.aet.job.common.comparators.source.visitors.NodeTraversor;
import com.cognifide.aet.job.common.comparators.source.diff.ResultDelta.TYPE;
import com.cognifide.aet.vs.ArtifactsDAO;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;

public class SourceComparator implements ComparatorJob {

private static final Logger LOGGER = LoggerFactory.getLogger(SourceComparator.class);

public static final String COMPARATOR_TYPE = "source";

public static final String COMPARATOR_NAME = "source";
class SourceComparator implements ComparatorJob {

private static final String SOURCE_COMPARE_TYPE = "compareType";

private final ComparatorProperties properties;

private final DiffParser diffParser;

private final ArtifactsDAO artifactsDAO;
private final Sources sources;

private SourceCompareType sourceCompareType = SourceCompareType.ALL;
private SourceCompareType sourceCompareType;

private final List<DataFilterJob> dataFilterJobs;
SourceComparator(ArtifactsDAO artifactsDAO, ComparatorProperties properties,
DiffParser diffParser, Sources sources) {

public SourceComparator(ArtifactsDAO artifactsDAO, ComparatorProperties properties,
DiffParser diffParser,
List<DataFilterJob> dataFilterJobs) {
this.artifactsDAO = artifactsDAO;
this.properties = properties;
this.diffParser = diffParser;
this.dataFilterJobs = dataFilterJobs;
this.sources = sources;
}

@Override
public void setParameters(final Map<String, String> params) throws ParametersException {
this.sourceCompareType =
Optional.ofNullable(params.get(SOURCE_COMPARE_TYPE))
.map(String::toUpperCase)
.map(SourceCompareType::valueOf)
.orElse(SourceCompareType.ALL);
}

@Override
@SuppressWarnings("unchecked")
public final ComparatorStepResult compare() throws ProcessingException {
final ComparatorStepResult result;
try {
String patternSource = formatCode(
artifactsDAO.getArtifactAsString(properties, properties.getPatternId()));
String dataSource = formatCode(
artifactsDAO.getArtifactAsString(properties, properties.getCollectedId()));

for (DataFilterJob<String> dataFilterJob : dataFilterJobs) {
LOGGER.info("Starting {}. Company: {} Project: {}",
dataFilterJob.getInfo(), properties.getCompany(), properties.getProject());

dataSource = dataFilterJob.modifyData(dataSource);

LOGGER.info("Successfully ended data modifications using {}. Company: {} Project: {}",
dataFilterJob.getInfo(), properties.getCompany(), properties.getProject());

patternSource = dataFilterJob.modifyPattern(patternSource);

LOGGER.info("Successfully ended pattern modifications using {}. Company: {} Project: {}",
dataFilterJob.getInfo(), properties.getCompany(), properties.getProject());
}

if (StringUtils.isNotBlank(patternSource)) {
boolean compareTrimmedLines = shouldCompareTrimmedLines(sourceCompareType);
final List<ResultDelta> deltas = diffParser
.generateDiffs(patternSource, dataSource, compareTrimmedLines);
if (deltas.isEmpty()) {
result = new ComparatorStepResult(null, ComparatorStepResult.Status.PASSED, false);
} else {
result = new ComparatorStepResult(artifactsDAO.saveArtifactInJsonFormat(properties,
Collections.singletonMap("differences", deltas)),
ComparatorStepResult.Status.FAILED, true);
result.addData("formattedPattern", artifactsDAO.saveArtifact(properties, patternSource));
result.addData("formattedSource", artifactsDAO.saveArtifact(properties, dataSource));
result.addData("sourceCompareType", sourceCompareType.name());
}
} else {
result = new ComparatorStepResult(null, ComparatorStepResult.Status.PASSED);
}
} catch (Exception e) {
throw new ProcessingException(e.getMessage(), e);
return compareSources();
} catch (Exception ex) {
throw new ProcessingException(ex.getMessage(), ex);
}

return result;
}

@SuppressWarnings("unchecked")
private ComparatorStepResult compareSources() throws IOException, ProcessingException {
sources.generate(sourceCompareType);
return getResultOfCompare();
}

private boolean shouldCompareTrimmedLines(SourceCompareType sourceCompareType) {
return SourceCompareType.ALLFORMATTED.equals(sourceCompareType)
|| SourceCompareType.MARKUP.equals(sourceCompareType);
private ComparatorStepResult getResultOfCompare() {
List<ResultDelta> deltas = calculateDeltas();
ComparatorStepResult.Status status = calculateStatus(deltas);
ComparatorStepResult result = createNewStepResult(deltas, status);
addFormattedSources(result);
return result;
}

@Override
public void setParameters(final Map<String, String> params) throws ParametersException {
if (params.containsKey(SOURCE_COMPARE_TYPE)) {
this.sourceCompareType = SourceCompareType
.valueOf(params.get(SOURCE_COMPARE_TYPE).toUpperCase());
}
private List<ResultDelta> calculateDeltas() {
return Optional.of(sources.getPatternSource())
.map(this::diffSources)
.orElse(new ArrayList<>());
}

private String formatCode(String code) {
String result;
switch (sourceCompareType) {
case MARKUP:
result = formatCodeMarkup(code);
break;
case CONTENT:
result = formatCodeContent(code);
break;
case ALLFORMATTED:
result = formatCodeAllFormatted(code);
break;
default:
result = code;
break;
}
return result;
private List<ResultDelta> diffSources(String patternSource) {
boolean compareTrimmedLines = shouldCompareTrimmedLines(sourceCompareType);
return diffParser.generateDiffs(patternSource, sources.getDataSource(), compareTrimmedLines);
}

private String formatCodeAllFormatted(String code) {
Document doc = Jsoup.parse(code);
return removeEmptyLines(doc.outerHtml());
private boolean shouldCompareTrimmedLines(SourceCompareType sourceCompareType) {
return SourceCompareType.ALLFORMATTED.equals(sourceCompareType)
|| SourceCompareType.MARKUP.equals(sourceCompareType);
}

// package scoped for unit test
String removeEmptyLines(String source) {
String result = source;
if (StringUtils.isNotBlank(source)) {
result = result.replaceAll("(?m)^[ \t]*[\r\n]+", "");
}
return result;
private Status calculateStatus(List<ResultDelta> deltas) {
return deltas.stream().anyMatch(d -> d.getType().equals(TYPE.CHANGE)) ?
Status.FAILED : Status.PASSED;
}

private String formatCodeContent(String code) {
Document doc = Jsoup.parse(code);
ContentVisitor visitor = new ContentVisitor();
NodeTraversor traversor = new NodeTraversor(visitor);
traversor.traverse(doc);
return visitor.getFormattedText();
private ComparatorStepResult createNewStepResult(List<ResultDelta> deltas, Status status) {
Map<String, List<ResultDelta>> differences = Collections.singletonMap("differences", deltas);
String artifactId = artifactsDAO.saveArtifactInJsonFormat(properties, differences);
boolean rebaseable = Status.FAILED.equals(status);
return new ComparatorStepResult(artifactId, status, rebaseable);
}

private String formatCodeMarkup(String code) {
Document doc = Jsoup.parse(code);
NodeTraversor traversor = new NodeTraversor(new MarkupVisitor());
traversor.traverse(doc);
return doc.html();
private void addFormattedSources(ComparatorStepResult result) {
String pattern = artifactsDAO.saveArtifact(properties, sources.getPatternSource());
String data = artifactsDAO.saveArtifact(properties, sources.getDataSource());
result.addData("formattedPattern", pattern);
result.addData("formattedSource", data);
result.addData("sourceCompareType", sourceCompareType.name());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,20 @@
@Component
public class SourceComparatorFactory implements ComparatorFactory {

private static final String COMPARATOR_TYPE = "source";
private static final String COMPARATOR_NAME = "source";

@Reference
private ArtifactsDAO artifactsDAO;

@Override
public final String getType() {
return SourceComparator.COMPARATOR_TYPE;
return COMPARATOR_TYPE;
}

@Override
public final String getName() {
return SourceComparator.COMPARATOR_NAME;
return COMPARATOR_NAME;
}

@Override
Expand All @@ -49,11 +52,12 @@ public final int getRanking() {
}

@Override
public ComparatorJob createInstance(Comparator comparator,
ComparatorProperties comparatorProperties, List<DataFilterJob> dataFilterJobs)
throws ParametersException {
final SourceComparator sourceComparator = new SourceComparator(artifactsDAO,
comparatorProperties, new DiffParser(), dataFilterJobs);
public ComparatorJob createInstance(Comparator comparator, ComparatorProperties properties,
List<DataFilterJob> filters) throws ParametersException {

Sources sources = new Sources(artifactsDAO, properties, filters, new CodeFormatter());
final SourceComparator sourceComparator = new SourceComparator(artifactsDAO, properties,
new DiffParser(), sources);
sourceComparator.setParameters(comparator.getParameters());
return sourceComparator;
}
Expand Down
Loading