org.sonar.server.benchmark.PersistFileSourcesStepTest.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.server.benchmark.PersistFileSourcesStepTest.java

Source

/*
 * SonarQube
 * Copyright (C) 2009-2016 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.server.benchmark;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.Constants;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.server.computation.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.batch.BatchReportDirectoryHolderImpl;
import org.sonar.server.computation.batch.BatchReportReaderImpl;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.ReportComponent;
import org.sonar.server.computation.duplication.Duplicate;
import org.sonar.server.computation.duplication.Duplication;
import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
import org.sonar.server.computation.duplication.InnerDuplicate;
import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.scm.ScmInfoRepositoryImpl;
import org.sonar.server.computation.source.SourceHashRepositoryImpl;
import org.sonar.server.computation.source.SourceLinesRepositoryImpl;
import org.sonar.server.computation.step.PersistFileSourcesStep;

import static org.assertj.core.api.Assertions.assertThat;

public class PersistFileSourcesStepTest {

    public static final Logger LOGGER = LoggerFactory.getLogger("perfTestPersistFileSourcesStep");

    public static final int NUMBER_OF_FILES = 1000;
    public static final int NUMBER_OF_LINES = 1000;
    public static final String PROJECT_UUID = Uuids.create();

    @Rule
    public TemporaryFolder temp = new TemporaryFolder();
    @Rule
    public DbTester dbTester = DbTester.create(System2.INSTANCE);
    @Rule
    public Benchmark benchmark = new Benchmark();
    @Rule
    public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
    @Rule
    public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
    @Rule
    public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);

    @Test
    public void benchmark() throws Exception {
        File reportDir = prepareReport();
        persistFileSources(reportDir);
    }

    private void persistFileSources(File reportDir) {
        LOGGER.info("Persist file sources");
        DbClient dbClient = dbTester.getDbClient();

        long start = System.currentTimeMillis();

        BatchReportDirectoryHolderImpl batchReportDirectoryHolder = new BatchReportDirectoryHolderImpl();
        batchReportDirectoryHolder.setDirectory(reportDir);
        org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(
                batchReportDirectoryHolder);
        analysisMetadataHolder.setBaseProjectSnapshot(null);
        SourceLinesRepositoryImpl sourceLinesRepository = new SourceLinesRepositoryImpl(batchReportReader);
        SourceHashRepositoryImpl sourceHashRepository = new SourceHashRepositoryImpl(sourceLinesRepository);
        ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader,
                analysisMetadataHolder, dbClient, sourceHashRepository);
        PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder,
                batchReportReader, sourceLinesRepository, scmInfoRepository, duplicationRepository);
        step.execute();

        long end = System.currentTimeMillis();
        long duration = end - start;

        assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(NUMBER_OF_FILES);
        LOGGER.info(String.format("File sources have been persisted in %d ms", duration));

        benchmark.expectAround("Duration to persist FILE_SOURCES", duration, 40000L,
                Benchmark.DEFAULT_ERROR_MARGIN_PERCENTS);
    }

    private File prepareReport() throws IOException {
        LOGGER.info("Create report");
        File reportDir = temp.newFolder();

        BatchReportWriter writer = new BatchReportWriter(reportDir);
        writer.writeMetadata(BatchReport.Metadata.newBuilder().setRootComponentRef(1).build());
        BatchReport.Component.Builder project = BatchReport.Component.newBuilder().setRef(1)
                .setType(Constants.ComponentType.PROJECT);

        List<Component> components = new ArrayList<>();
        for (int fileRef = 2; fileRef <= NUMBER_OF_FILES + 1; fileRef++) {
            ReportComponent component = ReportComponent.builder(Component.Type.FILE, fileRef)
                    .setUuid(Uuids.create()).setKey("PROJECT:" + fileRef).build();
            components.add(component);
        }
        treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID)
                .setKey("PROJECT").addChildren(components.toArray(new Component[components.size()])).build());
        for (int fileRef = 2; fileRef <= NUMBER_OF_FILES + 1; fileRef++) {
            generateFileReport(writer, fileRef);
            project.addChildRef(fileRef);
        }

        writer.writeComponent(project.build());

        return reportDir;
    }

    private Component generateFileReport(BatchReportWriter writer, int fileRef) throws IOException {
        LineData lineData = new LineData();
        for (int line = 1; line <= NUMBER_OF_LINES; line++) {
            lineData.generateLineData(line);
            duplicationRepository.add(fileRef, new Duplication(new TextBlock(line, line),
                    Arrays.<Duplicate>asList(new InnerDuplicate(new TextBlock(line + 1, line + 1)))));
        }
        writer.writeComponent(BatchReport.Component.newBuilder().setRef(fileRef)
                .setType(Constants.ComponentType.FILE).setLines(NUMBER_OF_LINES).build());

        FileUtils.writeLines(writer.getSourceFile(fileRef), lineData.lines);
        writer.writeComponentCoverage(fileRef, lineData.coverages);
        writer.writeComponentChangesets(lineData.changesetsBuilder.setComponentRef(fileRef).build());
        writer.writeComponentSyntaxHighlighting(fileRef, lineData.highlightings);
        writer.writeComponentSymbols(fileRef, lineData.symbols);

        return ReportComponent.builder(Component.Type.FILE, fileRef).setUuid(Uuids.create())
                .setKey("PROJECT:" + fileRef).build();
    }

    private static class LineData {
        List<String> lines = new ArrayList<>();
        BatchReport.Changesets.Builder changesetsBuilder = BatchReport.Changesets.newBuilder();
        List<BatchReport.Coverage> coverages = new ArrayList<>();
        List<BatchReport.SyntaxHighlighting> highlightings = new ArrayList<>();
        List<BatchReport.Symbol> symbols = new ArrayList<>();

        void generateLineData(int line) {
            lines.add("line-" + line);

            changesetsBuilder
                    .addChangeset(BatchReport.Changesets.Changeset.newBuilder().setAuthor("author-" + line)
                            .setDate(123456789L).setRevision("rev-" + line).build())
                    .addChangesetIndexByLine(line - 1);

            coverages.add(BatchReport.Coverage.newBuilder().setLine(line).setConditions(10).setUtHits(true)
                    .setUtCoveredConditions(2).setItHits(true).setItCoveredConditions(3)
                    .setOverallCoveredConditions(4).build());

            highlightings.add(BatchReport.SyntaxHighlighting.newBuilder()
                    .setRange(BatchReport.TextRange.newBuilder().setStartLine(line).setEndLine(line)
                            .setStartOffset(1).setEndOffset(3).build())
                    .setType(Constants.HighlightingType.ANNOTATION).build());

            symbols.add(BatchReport.Symbol.newBuilder()
                    .setDeclaration(BatchReport.TextRange.newBuilder().setStartLine(line).setEndLine(line)
                            .setStartOffset(2).setEndOffset(4).build())
                    .addReference(BatchReport.TextRange.newBuilder().setStartLine(line + 1).setEndLine(line + 1)
                            .setStartOffset(1).setEndOffset(3).build())
                    .build());
        }
    }

}