Source code should only be read from the report

Revert of SONAR-6843
This commit is contained in:
Julien Lancelot 2015-09-28 14:06:28 +02:00
parent 99374f79d0
commit 1775b82f78
8 changed files with 46 additions and 107 deletions

View File

@ -82,8 +82,7 @@ public class PersistFileSourcesStepTest {
BatchReportDirectoryHolderImpl batchReportDirectoryHolder = new BatchReportDirectoryHolderImpl(); BatchReportDirectoryHolderImpl batchReportDirectoryHolder = new BatchReportDirectoryHolderImpl();
batchReportDirectoryHolder.setDirectory(reportDir); batchReportDirectoryHolder.setDirectory(reportDir);
org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder); org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder);
PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder, batchReportReader, PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder, batchReportReader, new SourceLinesRepositoryImpl(batchReportReader));
new SourceLinesRepositoryImpl(dbClient, batchReportReader));
step.execute(); step.execute();
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();

View File

@ -26,11 +26,11 @@ import org.sonar.server.computation.component.Component;
public interface SourceLinesRepository { public interface SourceLinesRepository {
/** /**
* Return lines from a given component. If file sources is not in the report then we read it from the database. * Return lines from a given component from the report.
* *
* @throws NullPointerException if argument is {@code null} * @throws NullPointerException if argument is {@code null}
* @throws IllegalArgumentException if component is not a {@link org.sonar.server.computation.component.Component.Type#FILE} * @throws IllegalArgumentException if component is not a {@link org.sonar.server.computation.component.Component.Type#FILE}
* @throws IllegalStateException if the file has no source code in the report and in the database * @throws IllegalStateException if the file has no source code in the report
*/ */
CloseableIterator<String> readLines(Component component); CloseableIterator<String> readLines(Component component);
} }

View File

@ -20,28 +20,20 @@
package org.sonar.server.computation.source; package org.sonar.server.computation.source;
import com.google.common.base.Function;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import javax.annotation.Nonnull;
import org.sonar.core.util.CloseableIterator; import org.sonar.core.util.CloseableIterator;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.db.source.FileSourceDto;
import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import static com.google.common.collect.FluentIterable.from; import static com.google.common.base.Preconditions.checkState;
import static org.sonar.server.computation.component.Component.Type.FILE; import static org.sonar.server.computation.component.Component.Type.FILE;
public class SourceLinesRepositoryImpl implements SourceLinesRepository { public class SourceLinesRepositoryImpl implements SourceLinesRepository {
private final DbClient dbClient;
private final BatchReportReader reportReader; private final BatchReportReader reportReader;
public SourceLinesRepositoryImpl(DbClient dbClient, BatchReportReader reportReader) { public SourceLinesRepositoryImpl(BatchReportReader reportReader) {
this.dbClient = dbClient;
this.reportReader = reportReader; this.reportReader = reportReader;
} }
@ -53,33 +45,7 @@ public class SourceLinesRepositoryImpl implements SourceLinesRepository {
} }
Optional<CloseableIterator<String>> linesIteratorOptional = reportReader.readFileSource(component.getReportAttributes().getRef()); Optional<CloseableIterator<String>> linesIteratorOptional = reportReader.readFileSource(component.getReportAttributes().getRef());
if (linesIteratorOptional.isPresent()) { checkState(linesIteratorOptional.isPresent(), String.format("File '%s' has no source code", component));
return linesIteratorOptional.get(); return linesIteratorOptional.get();
}
DbSession session = dbClient.openSession(false);
try {
return readLinesFromDb(session, component);
} finally {
dbClient.closeSession(session);
}
} }
private CloseableIterator<String> readLinesFromDb(DbSession session, Component component) {
FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(session, component.getUuid());
if (dto == null) {
throw new IllegalStateException(String.format("The file '%s' has no source", component));
}
DbFileSources.Data data = dto.getSourceData();
return CloseableIterator.from(from(data.getLinesList()).transform(LineToRaw.INSTANCE).iterator());
}
private enum LineToRaw implements Function<DbFileSources.Line, String> {
INSTANCE;
@Override
public String apply(@Nonnull DbFileSources.Line line) {
return line.getSource();
}
}
} }

View File

@ -134,7 +134,7 @@ public class IntegrateIssuesVisitorTest {
.setSeverity(Constants.Severity.BLOCKER) .setSeverity(Constants.Severity.BLOCKER)
.build(); .build();
reportReader.putIssues(FILE_REF, asList(reportIssue)); reportReader.putIssues(FILE_REF, asList(reportIssue));
reportReader.putFileSourceLines(FILE_REF, "line1"); fileSourceRepository.addLine(FILE_REF, "line1");
underTest.visitAny(FILE); underTest.visitAny(FILE);
@ -164,7 +164,7 @@ public class IntegrateIssuesVisitorTest {
.setSeverity(Constants.Severity.BLOCKER) .setSeverity(Constants.Severity.BLOCKER)
.build(); .build();
reportReader.putIssues(FILE_REF, asList(reportIssue)); reportReader.putIssues(FILE_REF, asList(reportIssue));
reportReader.putFileSourceLines(FILE_REF, "line1"); fileSourceRepository.addLine(FILE_REF, "line1");
underTest.visitAny(FILE); underTest.visitAny(FILE);
@ -213,7 +213,7 @@ public class IntegrateIssuesVisitorTest {
.setSeverity(Constants.Severity.BLOCKER) .setSeverity(Constants.Severity.BLOCKER)
.build(); .build();
reportReader.putIssues(FILE_REF, asList(reportIssue)); reportReader.putIssues(FILE_REF, asList(reportIssue));
reportReader.putFileSourceLines(FILE_REF, "line1"); fileSourceRepository.addLine(FILE_REF, "line1");
underTest.visitAny(FILE); underTest.visitAny(FILE);
@ -252,7 +252,7 @@ public class IntegrateIssuesVisitorTest {
.setSeverity(Constants.Severity.BLOCKER) .setSeverity(Constants.Severity.BLOCKER)
.build(); .build();
reportReader.putIssues(FILE_REF, asList(reportIssue)); reportReader.putIssues(FILE_REF, asList(reportIssue));
reportReader.putFileSourceLines(FILE_REF, "line1"); fileSourceRepository.addLine(FILE_REF, "line1");
underTest.visitAny(FILE); underTest.visitAny(FILE);
@ -270,7 +270,7 @@ public class IntegrateIssuesVisitorTest {
.setSeverity(Constants.Severity.BLOCKER) .setSeverity(Constants.Severity.BLOCKER)
.build(); .build();
reportReader.putIssues(FILE_REF, asList(reportIssue)); reportReader.putIssues(FILE_REF, asList(reportIssue));
reportReader.putFileSourceLines(FILE_REF, "line1"); fileSourceRepository.addLine(FILE_REF, "line1");
underTest.visitAny(FILE); underTest.visitAny(FILE);
assertThat(componentIssuesRepository.getIssues(FILE_REF)).hasSize(1); assertThat(componentIssuesRepository.getIssues(FILE_REF)).hasSize(1);

View File

@ -45,8 +45,10 @@ import static org.mockito.Mockito.when;
public class TrackerRawInputFactoryTest { public class TrackerRawInputFactoryTest {
static int FILE_REF = 2;
static ReportComponent PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setKey("PROJECT_KEY_2").setUuid("PROJECT_UUID_1").build(); static ReportComponent PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setKey("PROJECT_KEY_2").setUuid("PROJECT_UUID_1").build();
static ReportComponent FILE = ReportComponent.builder(Component.Type.FILE, 2).setKey("FILE_KEY_2").setUuid("FILE_UUID_2").build(); static ReportComponent FILE = ReportComponent.builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY_2").setUuid("FILE_UUID_2").build();
@Rule @Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(PROJECT); public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(PROJECT);
@ -63,7 +65,7 @@ public class TrackerRawInputFactoryTest {
@Test @Test
public void load_source_hash_sequences() throws Exception { public void load_source_hash_sequences() throws Exception {
fileSourceRepository.addLine("line 1;").addLine("line 2;"); fileSourceRepository.addLines(FILE_REF, "line 1;", "line 2;");
Input<DefaultIssue> input = underTest.create(FILE); Input<DefaultIssue> input = underTest.create(FILE);
assertThat(input.getLineHashSequence()).isNotNull(); assertThat(input.getLineHashSequence()).isNotNull();
@ -84,7 +86,7 @@ public class TrackerRawInputFactoryTest {
@Test @Test
public void load_issues() throws Exception { public void load_issues() throws Exception {
fileSourceRepository.addLine("line 1;").addLine("line 2;"); fileSourceRepository.addLines(FILE_REF, "line 1;", "line 2;");
BatchReport.Issue reportIssue = BatchReport.Issue.newBuilder() BatchReport.Issue reportIssue = BatchReport.Issue.newBuilder()
.setLine(2) .setLine(2)
.setMsg("the message") .setMsg("the message")
@ -115,7 +117,7 @@ public class TrackerRawInputFactoryTest {
@Test @Test
public void ignore_report_issues_on_common_rules() throws Exception { public void ignore_report_issues_on_common_rules() throws Exception {
fileSourceRepository.addLine("line 1;").addLine("line 2;"); fileSourceRepository.addLines(FILE_REF, "line 1;", "line 2;");
BatchReport.Issue reportIssue = BatchReport.Issue.newBuilder() BatchReport.Issue reportIssue = BatchReport.Issue.newBuilder()
.setMsg("the message") .setMsg("the message")
.setRuleRepository(CommonRuleKeys.commonRepositoryForLang("java")) .setRuleRepository(CommonRuleKeys.commonRepositoryForLang("java"))
@ -131,7 +133,7 @@ public class TrackerRawInputFactoryTest {
@Test @Test
public void load_issues_of_compute_engine_common_rules() throws Exception { public void load_issues_of_compute_engine_common_rules() throws Exception {
fileSourceRepository.addLine("line 1;").addLine("line 2;"); fileSourceRepository.addLines(FILE_REF, "line 1;", "line 2;");
DefaultIssue ceIssue = new DefaultIssue() DefaultIssue ceIssue = new DefaultIssue()
.setRuleKey(RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage")) .setRuleKey(RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage"))
.setMessage("not enough coverage") .setMessage("not enough coverage")

View File

@ -23,18 +23,13 @@ package org.sonar.server.computation.source;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.db.source.FileSourceDto;
import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.computation.component.ReportComponent.builder; import static org.sonar.server.computation.component.ReportComponent.builder;
public class SourceLinesRepositoryTest { public class SourceLinesRepositoryImplTest {
static final String FILE_UUID = "FILE_UUID"; static final String FILE_UUID = "FILE_UUID";
static final String FILE_KEY = "FILE_KEY"; static final String FILE_KEY = "FILE_KEY";
@ -48,15 +43,10 @@ public class SourceLinesRepositoryTest {
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
@Rule @Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule(); public BatchReportReaderRule reportReader = new BatchReportReaderRule();
DbSession session = db.getSession(); SourceLinesRepositoryImpl underTest = new SourceLinesRepositoryImpl(reportReader);
SourceLinesRepositoryImpl underTest = new SourceLinesRepositoryImpl(db.getDbClient(), reportReader);
@Test @Test
public void read_lines_from_report() throws Exception { public void read_lines_from_report() throws Exception {
@ -75,18 +65,11 @@ public class SourceLinesRepositoryTest {
} }
@Test @Test
public void read_lines_from_database() throws Exception { public void fail_with_ISE_when_file_has_no_source() throws Exception {
insertFileSourceInDb("line1", "line2"); thrown.expect(IllegalStateException.class);
thrown.expectMessage("File 'ReportComponent{ref=2, key='FILE_KEY', type=FILE}' has no source code");
assertThat(underTest.readLines(FILE)).containsOnly("line1", "line2"); underTest.readLines(FILE);
}
@Test
public void read_from_report_even_if_source_exist_in_db() throws Exception {
reportReader.putFileSourceLines(FILE_REF, "report line1", "report line2");
insertFileSourceInDb("db line1", "db line2");
assertThat(underTest.readLines(FILE)).containsOnly("report line1", "report line2");
} }
@Test @Test
@ -105,16 +88,4 @@ public class SourceLinesRepositoryTest {
underTest.readLines(builder(Component.Type.PROJECT, 123).setKey("NotFile").build()); underTest.readLines(builder(Component.Type.PROJECT, 123).setKey("NotFile").build());
} }
private void insertFileSourceInDb(String... lines) {
DbFileSources.Data.Builder dataBuilder = DbFileSources.Data.newBuilder();
for (int i = 0; i < lines.length; i++) {
dataBuilder.addLinesBuilder().setLine(i + 1).setSource(lines[i]).build();
}
db.getDbClient().fileSourceDao().insert(session,
new FileSourceDto()
.setFileUuid(FILE_UUID).setProjectUuid("PROJECT_UUID")
.setSourceData(dataBuilder.build()));
session.commit();
}
} }

View File

@ -20,18 +20,21 @@
package org.sonar.server.computation.source; package org.sonar.server.computation.source;
import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap;
import java.util.ArrayList; import com.google.common.collect.Multimap;
import java.util.List; import java.util.Arrays;
import java.util.Collection;
import org.junit.rules.ExternalResource; import org.junit.rules.ExternalResource;
import org.sonar.core.util.CloseableIterator; import org.sonar.core.util.CloseableIterator;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.sonar.server.computation.component.Component.Type.FILE; import static org.sonar.server.computation.component.Component.Type.FILE;
public class SourceLinesRepositoryRule extends ExternalResource implements SourceLinesRepository { public class SourceLinesRepositoryRule extends ExternalResource implements SourceLinesRepository {
private List<String> lines = new ArrayList<>(); private Multimap<Integer, String> lines = ArrayListMultimap.create();
@Override @Override
protected void after() { protected void after() {
@ -40,15 +43,22 @@ public class SourceLinesRepositoryRule extends ExternalResource implements Sourc
@Override @Override
public CloseableIterator<String> readLines(Component component) { public CloseableIterator<String> readLines(Component component) {
Preconditions.checkNotNull(component, "Component should not be bull"); checkNotNull(component, "Component should not be bull");
if (!component.getType().equals(FILE)) { if (!component.getType().equals(FILE)) {
throw new IllegalArgumentException(String.format("Component '%s' is not a file", component)); throw new IllegalArgumentException(String.format("Component '%s' is not a file", component));
} }
return CloseableIterator.from(lines.iterator()); Collection<String> componentLines = lines.get(component.getReportAttributes().getRef());
checkState(!componentLines.isEmpty(), String.format("File '%s' has no source code", component));
return CloseableIterator.from(componentLines.iterator());
} }
public SourceLinesRepositoryRule addLine(String line){ public SourceLinesRepositoryRule addLine(int componentRef, String line) {
lines.add(line); this.lines.put(componentRef, line);
return this;
}
public SourceLinesRepositoryRule addLines(int componentRef, String... lines) {
this.lines.putAll(componentRef, Arrays.asList(lines));
return this; return this;
} }

View File

@ -20,12 +20,10 @@
package org.sonar.server.computation.step; package org.sonar.server.computation.step;
import com.google.common.base.Optional;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category; import org.junit.experimental.categories.Category;
import org.sonar.api.resources.Language;
import org.sonar.api.utils.System2; import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.Constants; import org.sonar.batch.protocol.Constants;
import org.sonar.batch.protocol.output.BatchReport; import org.sonar.batch.protocol.output.BatchReport;
@ -39,7 +37,6 @@ import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.ReportComponent; import org.sonar.server.computation.component.ReportComponent;
import org.sonar.server.computation.language.LanguageRepository;
import org.sonar.server.computation.source.SourceLinesRepositoryRule; import org.sonar.server.computation.source.SourceLinesRepositoryRule;
import org.sonar.test.DbTests; import org.sonar.test.DbTests;
@ -129,10 +126,10 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
reportReader.putComponent(BatchReport.Component.newBuilder() reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(FILE_REF) .setRef(FILE_REF)
.setType(Constants.ComponentType.FILE) .setType(Constants.ComponentType.FILE)
// Lines is set to 3 but only 2 lines are read from the file -> the last lines should be added // Lines is set to 3 but only 2 lines are read from the file -> the last lines should be added
.setLines(3) .setLines(3)
.build()); .build());
fileSourceRepository.addLine("line1").addLine("line2"); fileSourceRepository.addLines(FILE_REF, "line 1;", "line 2;");
underTest.execute(); underTest.execute();
@ -442,14 +439,8 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
.build()); .build());
for (int i = 1; i <= numberOfLines; i++) { for (int i = 1; i <= numberOfLines; i++) {
fileSourceRepository.addLine("line" + i); fileSourceRepository.addLine(FILE_REF, "line" + i);
} }
} }
private static class EmptyLanguageRepository implements LanguageRepository {
@Override
public Optional<Language> find(String languageKey) {
return Optional.absent();
}
}
} }