2 * SonarQube, open source software quality management tool.
3 * Copyright (C) 2008-2014 SonarSource
4 * mailto:contact AT sonarsource DOT com
6 * SonarQube is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * SonarQube is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 package org.sonar.server.benchmark;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.List;
27 import org.apache.commons.io.FileUtils;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.TemporaryFolder;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.sonar.api.utils.System2;
34 import org.sonar.batch.protocol.Constants;
35 import org.sonar.batch.protocol.output.BatchReport;
36 import org.sonar.batch.protocol.output.BatchReportWriter;
37 import org.sonar.core.util.Uuids;
38 import org.sonar.db.DbClient;
39 import org.sonar.db.DbTester;
40 import org.sonar.server.computation.batch.BatchReportDirectoryHolderImpl;
41 import org.sonar.server.computation.batch.BatchReportReaderImpl;
42 import org.sonar.server.computation.batch.TreeRootHolderRule;
43 import org.sonar.server.computation.component.Component;
44 import org.sonar.server.computation.component.ReportComponent;
45 import org.sonar.server.computation.source.SourceLinesRepositoryImpl;
46 import org.sonar.server.computation.step.PersistFileSourcesStep;
48 import static org.assertj.core.api.Assertions.assertThat;
50 public class PersistFileSourcesStepTest {
52 public static final Logger LOGGER = LoggerFactory.getLogger("perfTestPersistFileSourcesStep");
54 public static final int NUMBER_OF_FILES = 1000;
55 public static final int NUMBER_OF_LINES = 1000;
56 public static final String PROJECT_UUID = Uuids.create();
59 public TemporaryFolder temp = new TemporaryFolder();
62 public DbTester dbTester = DbTester.create(System2.INSTANCE);
65 public Benchmark benchmark = new Benchmark();
68 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
71 public void benchmark() throws Exception {
72 File reportDir = prepareReport();
73 persistFileSources(reportDir);
76 private void persistFileSources(File reportDir) {
77 LOGGER.info("Persist file sources");
78 DbClient dbClient = dbTester.getDbClient();
80 long start = System.currentTimeMillis();
82 BatchReportDirectoryHolderImpl batchReportDirectoryHolder = new BatchReportDirectoryHolderImpl();
83 batchReportDirectoryHolder.setDirectory(reportDir);
84 org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder);
85 PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder, batchReportReader, new SourceLinesRepositoryImpl(batchReportReader));
88 long end = System.currentTimeMillis();
89 long duration = end - start;
91 assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(NUMBER_OF_FILES);
92 LOGGER.info(String.format("File sources has been persisted in %d ms", duration));
94 benchmark.expectAround("Duration to persist FILE_SOURCES", duration, 125000, Benchmark.DEFAULT_ERROR_MARGIN_PERCENTS);
97 private File prepareReport() throws IOException {
98 LOGGER.info("Create report");
99 File reportDir = temp.newFolder();
101 BatchReportWriter writer = new BatchReportWriter(reportDir);
102 writer.writeMetadata(BatchReport.Metadata.newBuilder()
103 .setRootComponentRef(1)
105 BatchReport.Component.Builder project = BatchReport.Component.newBuilder()
107 .setType(Constants.ComponentType.PROJECT);
109 List<Component> components = new ArrayList<>();
110 for (int fileRef = 2; fileRef <= NUMBER_OF_FILES + 1; fileRef++) {
111 components.add(generateFileReport(writer, fileRef));
112 project.addChildRef(fileRef);
114 treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1)
115 .setUuid(PROJECT_UUID)
117 .addChildren(components.toArray(new Component[components.size()]))
120 writer.writeComponent(project.build());
125 private Component generateFileReport(BatchReportWriter writer, int fileRef) throws IOException {
126 LineData lineData = new LineData();
127 for (int line = 1; line <= NUMBER_OF_LINES; line++) {
128 lineData.generateLineData(line);
130 writer.writeComponent(BatchReport.Component.newBuilder()
132 .setType(Constants.ComponentType.FILE)
133 .setLines(NUMBER_OF_LINES)
136 FileUtils.writeLines(writer.getSourceFile(fileRef), lineData.lines);
137 writer.writeComponentCoverage(fileRef, lineData.coverages);
138 writer.writeComponentChangesets(lineData.changesetsBuilder.setComponentRef(fileRef).build());
139 writer.writeComponentSyntaxHighlighting(fileRef, lineData.highlightings);
140 writer.writeComponentSymbols(fileRef, lineData.symbols);
141 writer.writeComponentDuplications(fileRef, lineData.duplications);
143 return ReportComponent.builder(Component.Type.FILE, fileRef).setUuid(Uuids.create()).setKey("PROJECT:" + fileRef).build();
146 private static class LineData {
147 List<String> lines = new ArrayList<>();
148 BatchReport.Changesets.Builder changesetsBuilder = BatchReport.Changesets.newBuilder();
149 List<BatchReport.Coverage> coverages = new ArrayList<>();
150 List<BatchReport.SyntaxHighlighting> highlightings = new ArrayList<>();
151 List<BatchReport.Symbol> symbols = new ArrayList<>();
152 List<BatchReport.Duplication> duplications = new ArrayList<>();
154 void generateLineData(int line) {
155 lines.add("line-" + line);
157 changesetsBuilder.addChangeset(BatchReport.Changesets.Changeset.newBuilder()
158 .setAuthor("author-" + line)
160 .setRevision("rev-" + line)
162 .addChangesetIndexByLine(line - 1);
164 coverages.add(BatchReport.Coverage.newBuilder()
168 .setUtCoveredConditions(2)
170 .setItCoveredConditions(3)
171 .setOverallCoveredConditions(4)
174 highlightings.add(BatchReport.SyntaxHighlighting.newBuilder()
175 .setRange(BatchReport.TextRange.newBuilder()
176 .setStartLine(line).setEndLine(line)
177 .setStartOffset(1).setEndOffset(3)
179 .setType(Constants.HighlightingType.ANNOTATION)
182 symbols.add(BatchReport.Symbol.newBuilder()
183 .setDeclaration(BatchReport.TextRange.newBuilder()
184 .setStartLine(line).setEndLine(line).setStartOffset(2).setEndOffset(4)
186 .addReference(BatchReport.TextRange.newBuilder()
187 .setStartLine(line + 1).setEndLine(line + 1).setStartOffset(1).setEndOffset(3)
191 duplications.add(BatchReport.Duplication.newBuilder()
192 .setOriginPosition(BatchReport.TextRange.newBuilder()
196 .addDuplicate(BatchReport.Duplicate.newBuilder()
197 .setRange(BatchReport.TextRange.newBuilder()
198 .setStartLine(line + 1)
199 .setEndLine(line + 1)