From 83a047986ca0599ac48fd331611efcc46ab3154f Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 1 Dec 2014 09:33:38 +0100 Subject: Fix sonar-data-test --- server/pom.xml | 1 - server/sonar-data-test/pom.xml | 42 +--- .../java/org/sonar/data/issues/AbstractTest.java | 136 ------------ .../sonar/data/issues/IssuesDbExtractionTest.java | 185 ----------------- .../data/issues/IssuesIndexInjectionTest.java | 210 ------------------- .../server/benchmark/IssueIndexBenchmarkTest.java | 229 +++++++++++++++++++++ .../src/test/resources/assertions.properties | 4 - .../src/test/resources/logback-test.xml | 10 - server/sonar-server-benchmark/pom.xml | 68 ------ .../server/benchmark/IssueIndexBenchmarkTest.java | 229 --------------------- .../src/test/resources/logback-test.xml | 42 ---- 11 files changed, 238 insertions(+), 918 deletions(-) delete mode 100644 server/sonar-data-test/src/test/java/org/sonar/data/issues/AbstractTest.java delete mode 100644 server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesDbExtractionTest.java delete mode 100644 server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesIndexInjectionTest.java create mode 100644 server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java delete mode 100644 server/sonar-data-test/src/test/resources/assertions.properties delete mode 100644 server/sonar-server-benchmark/pom.xml delete mode 100644 server/sonar-server-benchmark/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java delete mode 100644 server/sonar-server-benchmark/src/test/resources/logback-test.xml diff --git a/server/pom.xml b/server/pom.xml index 4c5fa98f7df..7a5c9de19d8 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -17,6 +17,5 @@ sonar-server sonar-web sonar-ws-client - diff --git a/server/sonar-data-test/pom.xml b/server/sonar-data-test/pom.xml index 25d326cfbc6..02417b40099 100644 --- a/server/sonar-data-test/pom.xml +++ b/server/sonar-data-test/pom.xml @@ -4,66 +4,43 @@ 4.0.0 org.codehaus.sonar - sonar + server 5.0-SNAPSHOT + .. sonar-data-test - jar - SonarQube :: Server :: Data Tests + SonarQube :: Server :: Benchmark org.codehaus.sonar sonar-server - test-jar - test ${project.version} + test org.codehaus.sonar sonar-server + test-jar ${project.version} + test org.codehaus.sonar sonar-search ${project.version} - - - org.codehaus.sonar - sonar-core - ${project.version} - - - org.codehaus.sonar - sonar-core - test-jar test - ${project.version} com.google.guava guava - - - org.easytesting - fest-assert test - junit - junit - test - - - org.dbunit - dbunit + org.codehaus.sonar + sonar-testing-harness test - - org.mockito - mockito-core - @@ -72,8 +49,7 @@ org.apache.maven.plugins maven-surefire-plugin - ${skipServerTests} - -Xmx256m + -Xmx1G -Xms256m -server -Djava.awt.headless=true diff --git a/server/sonar-data-test/src/test/java/org/sonar/data/issues/AbstractTest.java b/server/sonar-data-test/src/test/java/org/sonar/data/issues/AbstractTest.java deleted file mode 100644 index b8932803c88..00000000000 --- a/server/sonar-data-test/src/test/java/org/sonar/data/issues/AbstractTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.data.issues; - -import com.google.common.collect.Iterables; -import org.apache.commons.lang.StringUtils; -import org.apache.ibatis.io.Resources; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.rules.TestName; -import org.sonar.api.issue.Issue; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; -import org.sonar.core.component.ComponentDto; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.rule.RuleDto; -import org.sonar.server.issue.IssueTesting; -import org.sonar.server.rule.RuleTesting; - -import java.io.File; -import java.io.FileReader; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; - -import static com.google.common.collect.Lists.newArrayList; -import static org.fest.assertions.Assertions.assertThat; - -public class AbstractTest { - - final static int RULES_NUMBER = 25; - final static int USERS_NUMBER = 100; - - private static final double ACCEPTED_DURATION_VARIATION_IN_PERCENTS = 10.0; - - static Iterator rules; - static Iterator users; - static Iterator severities; - static Iterator statuses; - static Iterator closedResolutions; - static Iterator resolvedResolutions; - - static Properties properties = new Properties(); - @Rule - public TestName testName = new TestName(); - - @BeforeClass - public static void loadProperties() { - try { - properties = new Properties(); - File propertiesFile = Resources.getResourceAsFile("assertions.properties"); - FileReader reader = new FileReader(propertiesFile); - properties.load(reader); - properties.putAll(System.getProperties()); - } catch (Exception e) { - throw new IllegalStateException(e); - } - - severities = Iterables.cycle(Severity.ALL).iterator(); - statuses = Iterables.cycle(Issue.STATUS_OPEN, Issue.STATUS_CONFIRMED, Issue.STATUS_REOPENED, Issue.STATUS_RESOLVED, Issue.STATUS_CLOSED).iterator(); - closedResolutions = Iterables.cycle(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED, Issue.RESOLUTION_REMOVED).iterator(); - resolvedResolutions = Iterables.cycle(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED).iterator(); - users = Iterables.cycle(generateUsers()).iterator(); - rules = Iterables.cycle(generateRules()).iterator(); - } - - protected static List generateRules() { - List rules = newArrayList(); - for (int i = 0; i < RULES_NUMBER; i++) { - rules.add(RuleTesting.newDto(RuleKey.of("rule-repo", "rule-key-" + i))); - } - return rules; - } - - protected static List generateUsers() { - List users = newArrayList(); - for (int i = 0; i < USERS_NUMBER; i++) { - users.add("user-" + i); - } - return users; - } - - protected String getProperty(String test) { - String currentUser = StringUtils.defaultString(properties.getProperty("user"), "default"); - String property = currentUser + "." + test; - String value = properties.getProperty(property); - if (value == null) { - throw new IllegalArgumentException(String.format("Property '%s' hasn't been found", property)); - } - return value; - } - - protected void assertDurationAround(long duration, long expectedDuration) { - double variation = 100.0 * (0.0 + duration - expectedDuration) / expectedDuration; - System.out.printf("Test %s : executed in %d ms (%.2f %% from target)\n", testName.getMethodName(), duration, variation); - assertThat(Math.abs(variation)).as(String.format("Expected %d ms, got %d ms", expectedDuration, duration)).isLessThan(ACCEPTED_DURATION_VARIATION_IN_PERCENTS); - } - - protected IssueDto newIssue(int index, ComponentDto file, ComponentDto project, RuleDto rule) { - String status = statuses.next(); - String resolution = null; - if (status.equals(Issue.STATUS_CLOSED)) { - resolution = closedResolutions.next(); - } else if (status.equals(Issue.STATUS_RESOLVED)) { - resolution = resolvedResolutions.next(); - } - return IssueTesting.newDto(rule, file, project) - .setMessage("Message from rule " + rule.getKey().toString() + " on line " + index) - .setLine(index) - .setAssignee(users.next()) - .setReporter(users.next()) - .setAuthorLogin(users.next()) - .setSeverity(severities.next()) - .setStatus(status) - .setResolution(resolution); - } - -} diff --git a/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesDbExtractionTest.java b/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesDbExtractionTest.java deleted file mode 100644 index 35c5aff9e9b..00000000000 --- a/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesDbExtractionTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.data.issues; - -import org.apache.ibatis.session.ResultContext; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.utils.System2; -import org.sonar.core.component.ComponentDto; -import org.sonar.core.persistence.DbSession; -import org.sonar.core.persistence.TestDatabase; -import org.sonar.server.component.ComponentTesting; -import org.sonar.server.component.db.ComponentDao; -import org.sonar.server.issue.db.IssueDao; -import org.sonar.server.rule.db.RuleDao; -import org.sonar.server.search.DbSynchronizationHandler; - -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicLong; - -import static org.fest.assertions.Assertions.assertThat; - -@Ignore("Waiting for usage of IssueIndexer") -public class IssuesDbExtractionTest extends AbstractTest { - - static final Logger LOGGER = LoggerFactory.getLogger(IssuesDbExtractionTest.class); - final static int PROJECTS_NUMBER = 100; - final static int NUMBER_FILES_PER_PROJECT = 100; - final static int NUMBER_ISSUES_PER_FILE = 100; - final static int ISSUE_COUNT = PROJECTS_NUMBER * NUMBER_FILES_PER_PROJECT * NUMBER_ISSUES_PER_FILE; - @Rule - public TestDatabase db = new TestDatabase(); - AtomicLong counter = new AtomicLong(0L); - DbSession session; - - ProxyIssueDao issueDao; - RuleDao ruleDao; - ComponentDao componentDao; - - @Before - public void setUp() throws Exception { - issueDao = new ProxyIssueDao(); - ruleDao = new RuleDao(); - componentDao = new ComponentDao(System2.INSTANCE); - - session = db.myBatis().openSession(false); - } - - @After - public void closeSession() throws Exception { - session.close(); - } - - @Test - public void extract_issues() throws Exception { - insertReferentials(); - - ProgressTask progressTask = new ProgressTask(counter); - Timer timer = new Timer("Extract Issues"); - timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS); - try { - long start = System.currentTimeMillis(); - issueDao.synchronizeAfter(session); - long stop = System.currentTimeMillis(); - progressTask.log(); - - assertThat(issueDao.synchronizedIssues).isEqualTo(ISSUE_COUNT); - - long time = stop - start; - LOGGER.info("Iterated over {} issues in {} ms with avg of {} issues/second", ISSUE_COUNT, time, rowsPerSecond(time)); - // assertDurationAround(time, Long.parseLong(getProperty("IssuesDbExtractionTest.extract_issues"))); - - } finally { - timer.cancel(); - timer.purge(); - } - } - - private void insertReferentials() { - long start = System.currentTimeMillis(); - - for (int i = 0; i < RULES_NUMBER; i++) { - ruleDao.insert(session, rules.next()); - } - session.commit(); - - for (long projectIndex = 0; projectIndex < PROJECTS_NUMBER; projectIndex++) { - ComponentDto project = ComponentTesting.newProjectDto() - .setKey("project-" + projectIndex) - .setName("Project " + projectIndex) - .setLongName("Project " + projectIndex); - componentDao.insert(session, project); - - for (int fileIndex = 0; fileIndex < NUMBER_FILES_PER_PROJECT; fileIndex++) { - String index = projectIndex * PROJECTS_NUMBER + fileIndex + ""; - ComponentDto file = ComponentTesting.newFileDto(project) - .setKey("file-" + index) - .setName("File " + index) - .setLongName("File " + index); - componentDao.insert(session, file); - - for (int issueIndex = 1; issueIndex < NUMBER_ISSUES_PER_FILE + 1; issueIndex++) { - issueDao.insert(session, newIssue(issueIndex, file, project, rules.next())); - } - session.commit(); - } - } - LOGGER.info("Referentials inserted in {} ms", System.currentTimeMillis() - start); - } - - protected int rowsPerSecond(long time) { - return (int) Math.round(ISSUE_COUNT / (time / 1000.0)); - } - - protected static class ProgressTask extends TimerTask { - - public static final long PERIOD_MS = 60000L; - private static final Logger LOGGER = LoggerFactory.getLogger("PerformanceTests"); - private final AtomicLong counter; - - public ProgressTask(AtomicLong counter) { - this.counter = counter; - } - - @Override - public void run() { - log(); - } - - public void log() { - LOGGER.info(String.format("%d issues processed", counter.get())); - } - } - - class ProxyIssueDao extends IssueDao { - public Integer synchronizedIssues = 0; - - @Override - protected boolean hasIndex() { - return false; - } - - @Override - protected DbSynchronizationHandler getSynchronizationResultHandler(DbSession session, Map params) { - return new DbSynchronizationHandler(session, params) { - - @Override - public void handleResult(ResultContext context) { - synchronizedIssues++; - counter.getAndIncrement(); - } - - @Override - public void enqueueCollected() { - - } - }; - } - } - -} diff --git a/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesIndexInjectionTest.java b/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesIndexInjectionTest.java deleted file mode 100644 index 26bac01f6a6..00000000000 --- a/server/sonar-data-test/src/test/java/org/sonar/data/issues/IssuesIndexInjectionTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.data.issues; - -import com.google.common.collect.ArrayListMultimap; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.issue.Issue; -import org.sonar.api.security.DefaultGroups; -import org.sonar.core.component.ComponentDto; -import org.sonar.core.issue.db.IssueAuthorizationDto; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.persistence.DbSession; -import org.sonar.server.component.ComponentTesting; -import org.sonar.server.db.DbClient; -import org.sonar.server.issue.IssueQuery; -import org.sonar.server.issue.index.IssueAuthorizationIndex; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.search.IndexDefinition; -import org.sonar.server.search.QueryContext; -import org.sonar.server.search.Result; -import org.sonar.server.search.action.InsertDto; -import org.sonar.server.search.action.RefreshIndex; -import org.sonar.server.tester.ServerTester; -import org.sonar.server.user.MockUserSession; - -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicLong; - -import static com.google.common.collect.Lists.newArrayList; -import static org.fest.assertions.Assertions.assertThat; - -public class IssuesIndexInjectionTest extends AbstractTest { - - static final Logger LOGGER = LoggerFactory.getLogger(IssuesIndexInjectionTest.class); - final static int PROJECTS = 100; - final static int FILES_PER_PROJECT = 100; - final static int ISSUES_PER_FILE = 100; - final static int ISSUE_COUNT = PROJECTS * FILES_PER_PROJECT * ISSUES_PER_FILE; - - @ClassRule - public static ServerTester tester = new ServerTester(); - AtomicLong counter = new AtomicLong(0L); - DbSession batchSession; - - IssueIndex issueIndex; - IssueAuthorizationIndex issueAuthorizationIndex; - - List projects = newArrayList(); - ArrayListMultimap componentsByProject = ArrayListMultimap.create(); - - protected static int documentPerSecond(long nbIssues, long time) { - return (int) Math.round(nbIssues / (time / 1000.0)); - } - - @Before - public void setUp() throws Exception { - issueIndex = tester.get(IssueIndex.class); - issueAuthorizationIndex = tester.get(IssueAuthorizationIndex.class); - batchSession = tester.get(DbClient.class).openSession(true); - - MockUserSession.set().setLogin("test"); - } - - @After - public void after() throws Exception { - batchSession.close(); - } - - @Test - public void inject_issues_and_execute_queries() throws Exception { - generateData(); - injectIssuesInIndex(); - executeQueries(); - } - - public void injectIssuesInIndex() { - ProgressTask progressTask = new ProgressTask(counter); - Timer timer = new Timer("Inject Issues"); - timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS); - try { - long start = System.currentTimeMillis(); - for (ComponentDto project : projects) { - for (ComponentDto file : componentsByProject.get(project)) { - for (int issueIndex = 1; issueIndex < ISSUES_PER_FILE + 1; issueIndex++) { - batchSession.enqueue(new InsertDto(IndexDefinition.ISSUES.getIndexType(), newIssue(issueIndex, file, project, rules.next()), false)); - counter.getAndIncrement(); - } - } - } - batchSession.enqueue(new RefreshIndex(IndexDefinition.ISSUES.getIndexType())); - batchSession.commit(); - long stop = System.currentTimeMillis(); - progressTask.log(); - - assertThat(issueIndex.countAll()).isEqualTo(ISSUE_COUNT); - - long totalTime = stop - start; - LOGGER.info("Inserted {} Issues in {} ms with avg {} Issue/second", ISSUE_COUNT, totalTime, documentPerSecond(ISSUE_COUNT, totalTime)); - // assertDurationAround(totalTime, Long.parseLong(getProperty("IssuesIndexInjectionTest.inject_issues"))); - - } finally { - timer.cancel(); - timer.purge(); - } - } - - public void executeQueries() { - long start = System.currentTimeMillis(); - Result result = issueIndex.search(IssueQuery.builder().build(), new QueryContext()); - LOGGER.info("Search for all issues : returned {} issues in {} ms", result.getTotal(), System.currentTimeMillis() - start); - - start = System.currentTimeMillis(); - ComponentDto project = componentsByProject.keySet().iterator().next(); - result = issueIndex.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()); - LOGGER.info("Search for issues from one project : returned {} issues in {} ms", result.getTotal(), System.currentTimeMillis() - start); - - start = System.currentTimeMillis(); - ComponentDto file = componentsByProject.get(project).get(0); - result = issueIndex.search(IssueQuery.builder().componentUuids(newArrayList(file.uuid())).build(), new QueryContext()); - LOGGER.info("Search for issues from one file : returned {} issues in {} ms", result.getTotal(), System.currentTimeMillis() - start); - } - - private void generateData() { - long ids = 1; - - for (int i = 0; i < RULES_NUMBER; i++) { - rules.next().setId((int) ids++); - } - - long start = System.currentTimeMillis(); - for (long projectIndex = 0; projectIndex < PROJECTS; projectIndex++) { - ComponentDto project = ComponentTesting.newProjectDto() - .setId(ids++) - .setKey("project-" + projectIndex) - .setName("Project " + projectIndex) - .setLongName("Project " + projectIndex); - projects.add(project); - - // All project are visible by anyone - // TODO set different groups/users to test search issues queries with more realistic data - batchSession.enqueue(new InsertDto(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType(), - new IssueAuthorizationDto().setProjectUuid(project.uuid()).setGroups(newArrayList(DefaultGroups.ANYONE)), false)); - - for (int fileIndex = 0; fileIndex < FILES_PER_PROJECT; fileIndex++) { - String index = projectIndex * PROJECTS + fileIndex + ""; - ComponentDto file = ComponentTesting.newFileDto(project) - .setId(ids++) - .setKey("file-" + index) - .setName("File " + index) - .setLongName("File " + index); - componentsByProject.put(project, file); - } - } - batchSession.enqueue(new RefreshIndex(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType())); - batchSession.commit(); - LOGGER.info("Generated data in {} ms", System.currentTimeMillis() - start); - } - - protected static class ProgressTask extends TimerTask { - - public static final long PERIOD_MS = 60000L; - private static final Logger LOGGER = LoggerFactory.getLogger("PerformanceTests"); - private final AtomicLong counter; - private long currentStart; - private long previousTotal = 0; - - public ProgressTask(AtomicLong counter) { - this.counter = counter; - this.currentStart = System.currentTimeMillis(); - } - - @Override - public void run() { - log(); - } - - public void log() { - long currentNumberOfIssues = counter.get() - this.previousTotal; - LOGGER.info("{} issues inserted with avg {} issue/second", currentNumberOfIssues, documentPerSecond(currentNumberOfIssues, System.currentTimeMillis() - this.currentStart)); - this.previousTotal = counter.get(); - this.currentStart = System.currentTimeMillis(); - } - } - -} diff --git a/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java new file mode 100644 index 00000000000..6d1eee42a19 --- /dev/null +++ b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java @@ -0,0 +1,229 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.lang.math.RandomUtils; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.issue.Issue; +import org.sonar.api.rule.Severity; +import org.sonar.api.utils.internal.Uuids; +import org.sonar.server.issue.IssueQuery; +import org.sonar.server.issue.index.IssueAuthorizationDao; +import org.sonar.server.issue.index.IssueAuthorizationIndexer; +import org.sonar.server.issue.index.IssueDoc; +import org.sonar.server.issue.index.IssueIndex; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.search.QueryContext; +import org.sonar.server.search.Result; +import org.sonar.server.tester.ServerTester; + +import java.util.Arrays; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicLong; + +public class IssueIndexBenchmarkTest { + + private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkIssues"); + + final static int PROJECTS = 100; + final static int FILES_PER_PROJECT = 100; + final static int ISSUES_PER_FILE = 100; + + @ClassRule + public static ServerTester tester = new ServerTester(); + + @Test + public void benchmark() throws Exception { + // initialization - feed issues/issueAuthorization with projects and hardcoded users + indexAuthorizations(); + + // index issues + benchmarkIssueIndexing(); + + // execute some queries + benchmarkQueries(); + } + + private void indexAuthorizations() { + IssueAuthorizationIndexer indexer = tester.get(IssueAuthorizationIndexer.class); + List authorizations = Lists.newArrayList(); + for (int i = 0; i < PROJECTS; i++) { + IssueAuthorizationDao.Dto authorization = new IssueAuthorizationDao.Dto("PROJECT" + i, System.currentTimeMillis()); + authorization.addGroup("sonar-users"); + authorization.addUser("admin"); + authorizations.add(authorization); + } + indexer.index(authorizations); + } + + private void benchmarkIssueIndexing() { + LOGGER.info("Indexing issues"); + IssueIterator issues = new IssueIterator(PROJECTS, FILES_PER_PROJECT, ISSUES_PER_FILE); + ProgressTask progressTask = new ProgressTask("issues", issues.count()); + Timer timer = new Timer("IssuesIndex"); + timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS); + + long start = System.currentTimeMillis(); + tester.get(IssueIndexer.class).index(issues); + long end = System.currentTimeMillis(); + + timer.cancel(); + long period = end - start; + LOGGER.info(String.format("%d issues indexed in %d ms (%d/second)", issues.count.get(), period, 1000 * issues.count.get() / period)); + } + + private void benchmarkQueries() { + benchmarkQuery("all issues", IssueQuery.builder().build()); + benchmarkQuery("project issues", IssueQuery.builder().projectUuids(Arrays.asList("PROJECT33")).build()); + benchmarkQuery("file issues", IssueQuery.builder().componentUuids(Arrays.asList("FILE333")).build()); + benchmarkQuery("various", IssueQuery.builder() + .resolutions(Arrays.asList(Issue.RESOLUTION_FIXED)) + .assigned(true) + .build()); + // TODO test facets + } + + private void benchmarkQuery(String label, IssueQuery query) { + IssueIndex index = tester.get(IssueIndex.class); + for (int i = 0; i < 10; i++) { + long start = System.currentTimeMillis(); + Result result = index.search(query, new QueryContext()); + long end = System.currentTimeMillis(); + LOGGER.info("Request (" + label + "): {} docs in {} ms", result.getTotal(), end - start); + } + } + + private static class IssueIterator implements Iterator { + private final int nbProjects, nbFilesPerProject, nbIssuesPerFile; + private int currentProject = 0, currentFile = 0; + private AtomicLong count = new AtomicLong(0L); + private final Iterator users = cycleIterator("guy", 200); + private Iterator rules = cycleIterator("squid:rule", 1000); + private final Iterator severities = Iterables.cycle(Severity.ALL).iterator(); + private final Iterator statuses = Iterables.cycle(Issue.STATUSES).iterator(); + private final Iterator resolutions = Iterables.cycle(Issue.RESOLUTIONS).iterator(); + + IssueIterator(int nbProjects, int nbFilesPerProject, int nbIssuesPerFile) { + this.nbProjects = nbProjects; + this.nbFilesPerProject = nbFilesPerProject; + this.nbIssuesPerFile = nbIssuesPerFile; + } + + public AtomicLong count() { + return count; + } + + @Override + public boolean hasNext() { + return count.get() < nbProjects * nbFilesPerProject * nbIssuesPerFile; + } + + @Override + public IssueDoc next() { + IssueDoc issue = new IssueDoc(Maps.newHashMap()); + issue.setKey(Uuids.create()); + issue.setFilePath("src/main/java/Foo" + currentFile); + issue.setComponentUuid("FILE" + currentFile); + issue.setProjectUuid("PROJECT" + currentProject); + issue.setActionPlanKey("PLAN" + currentProject); + issue.setAssignee(users.next()); + issue.setAuthorLogin(users.next()); + issue.setLine(RandomUtils.nextInt()); + issue.setCreationDate(new Date()); + issue.setUpdateDate(new Date()); + issue.setFuncUpdateDate(new Date()); + issue.setFuncCreationDate(new Date()); + issue.setFuncCloseDate(null); + issue.setAttributes(null); + issue.setDebt(1000L); + issue.setEffortToFix(3.14); + issue.setLanguage("php"); + issue.setReporter(users.next()); + issue.setRuleKey(rules.next()); + issue.setResolution(resolutions.next()); + issue.setStatus(statuses.next()); + issue.setSeverity(severities.next()); + issue.setMessage(RandomUtils.nextLong() + "this is the message. Not too short."); + count.incrementAndGet(); + if (count.get() % nbIssuesPerFile == 0) { + currentFile++; + } + if (count.get() % (nbFilesPerProject * nbIssuesPerFile) == 0) { + currentProject++; + } + + return issue; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private static Iterator cycleIterator(String prefix, int size) { + List values = Lists.newArrayList(); + for (int i = 0; i < size; i++) { + values.add(String.format("%s%d", prefix, i)); + } + return Iterators.cycle(values); + } + + static class ProgressTask extends TimerTask { + public static final long PERIOD_MS = 60000L; + + private final String label; + private final AtomicLong counter; + private long previousCount = 0L; + private long previousTime = 0L; + + public ProgressTask(String label, AtomicLong counter) { + this.label = label; + this.counter = counter; + this.previousTime = System.currentTimeMillis(); + } + + @Override + public void run() { + long currentCount = counter.get(); + long now = System.currentTimeMillis(); + LOGGER.info("{} {} indexed ({} {}/second)", + currentCount, label, documentsPerSecond(currentCount - previousCount, now - previousTime), label); + this.previousCount = currentCount; + this.previousTime = now; + } + } + + static int documentsPerSecond(long nbIssues, long time) { + return (int) Math.round(nbIssues / (time / 1000.0)); + } +} diff --git a/server/sonar-data-test/src/test/resources/assertions.properties b/server/sonar-data-test/src/test/resources/assertions.properties deleted file mode 100644 index 1d79daef696..00000000000 --- a/server/sonar-data-test/src/test/resources/assertions.properties +++ /dev/null @@ -1,4 +0,0 @@ -default.IssuesDbExtractionTest.extract_issues=40000 -default.IssuesIndexInjectionTest.inject_issues=40000 -JL.IssuesDbExtractionTest.extract_issues=40000 -JL.IssuesIndexInjectionTest.inject_issues=40000 diff --git a/server/sonar-data-test/src/test/resources/logback-test.xml b/server/sonar-data-test/src/test/resources/logback-test.xml index e595060acc0..69842078d6e 100644 --- a/server/sonar-data-test/src/test/resources/logback-test.xml +++ b/server/sonar-data-test/src/test/resources/logback-test.xml @@ -24,16 +24,6 @@ - - - - - - - - - - diff --git a/server/sonar-server-benchmark/pom.xml b/server/sonar-server-benchmark/pom.xml deleted file mode 100644 index 5ac1d25dfbd..00000000000 --- a/server/sonar-server-benchmark/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 4.0.0 - - org.codehaus.sonar - server - 5.0-SNAPSHOT - .. - - sonar-server-benchmark - SonarQube :: Server :: Benchmark - - - - org.codehaus.sonar - sonar-server - test-jar - test - ${project.version} - - - org.codehaus.sonar - sonar-server - ${project.version} - - - org.codehaus.sonar - sonar-search - ${project.version} - - - org.codehaus.sonar - sonar-core - ${project.version} - - - org.codehaus.sonar - sonar-core - test-jar - test - ${project.version} - - - com.google.guava - guava - - - org.codehaus.sonar - sonar-testing-harness - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - ${skipServerTests} - -Xmx256m - - - - - - diff --git a/server/sonar-server-benchmark/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java b/server/sonar-server-benchmark/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java deleted file mode 100644 index 6d1eee42a19..00000000000 --- a/server/sonar-server-benchmark/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.lang.math.RandomUtils; -import org.junit.ClassRule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.issue.Issue; -import org.sonar.api.rule.Severity; -import org.sonar.api.utils.internal.Uuids; -import org.sonar.server.issue.IssueQuery; -import org.sonar.server.issue.index.IssueAuthorizationDao; -import org.sonar.server.issue.index.IssueAuthorizationIndexer; -import org.sonar.server.issue.index.IssueDoc; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.search.QueryContext; -import org.sonar.server.search.Result; -import org.sonar.server.tester.ServerTester; - -import java.util.Arrays; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicLong; - -public class IssueIndexBenchmarkTest { - - private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkIssues"); - - final static int PROJECTS = 100; - final static int FILES_PER_PROJECT = 100; - final static int ISSUES_PER_FILE = 100; - - @ClassRule - public static ServerTester tester = new ServerTester(); - - @Test - public void benchmark() throws Exception { - // initialization - feed issues/issueAuthorization with projects and hardcoded users - indexAuthorizations(); - - // index issues - benchmarkIssueIndexing(); - - // execute some queries - benchmarkQueries(); - } - - private void indexAuthorizations() { - IssueAuthorizationIndexer indexer = tester.get(IssueAuthorizationIndexer.class); - List authorizations = Lists.newArrayList(); - for (int i = 0; i < PROJECTS; i++) { - IssueAuthorizationDao.Dto authorization = new IssueAuthorizationDao.Dto("PROJECT" + i, System.currentTimeMillis()); - authorization.addGroup("sonar-users"); - authorization.addUser("admin"); - authorizations.add(authorization); - } - indexer.index(authorizations); - } - - private void benchmarkIssueIndexing() { - LOGGER.info("Indexing issues"); - IssueIterator issues = new IssueIterator(PROJECTS, FILES_PER_PROJECT, ISSUES_PER_FILE); - ProgressTask progressTask = new ProgressTask("issues", issues.count()); - Timer timer = new Timer("IssuesIndex"); - timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS); - - long start = System.currentTimeMillis(); - tester.get(IssueIndexer.class).index(issues); - long end = System.currentTimeMillis(); - - timer.cancel(); - long period = end - start; - LOGGER.info(String.format("%d issues indexed in %d ms (%d/second)", issues.count.get(), period, 1000 * issues.count.get() / period)); - } - - private void benchmarkQueries() { - benchmarkQuery("all issues", IssueQuery.builder().build()); - benchmarkQuery("project issues", IssueQuery.builder().projectUuids(Arrays.asList("PROJECT33")).build()); - benchmarkQuery("file issues", IssueQuery.builder().componentUuids(Arrays.asList("FILE333")).build()); - benchmarkQuery("various", IssueQuery.builder() - .resolutions(Arrays.asList(Issue.RESOLUTION_FIXED)) - .assigned(true) - .build()); - // TODO test facets - } - - private void benchmarkQuery(String label, IssueQuery query) { - IssueIndex index = tester.get(IssueIndex.class); - for (int i = 0; i < 10; i++) { - long start = System.currentTimeMillis(); - Result result = index.search(query, new QueryContext()); - long end = System.currentTimeMillis(); - LOGGER.info("Request (" + label + "): {} docs in {} ms", result.getTotal(), end - start); - } - } - - private static class IssueIterator implements Iterator { - private final int nbProjects, nbFilesPerProject, nbIssuesPerFile; - private int currentProject = 0, currentFile = 0; - private AtomicLong count = new AtomicLong(0L); - private final Iterator users = cycleIterator("guy", 200); - private Iterator rules = cycleIterator("squid:rule", 1000); - private final Iterator severities = Iterables.cycle(Severity.ALL).iterator(); - private final Iterator statuses = Iterables.cycle(Issue.STATUSES).iterator(); - private final Iterator resolutions = Iterables.cycle(Issue.RESOLUTIONS).iterator(); - - IssueIterator(int nbProjects, int nbFilesPerProject, int nbIssuesPerFile) { - this.nbProjects = nbProjects; - this.nbFilesPerProject = nbFilesPerProject; - this.nbIssuesPerFile = nbIssuesPerFile; - } - - public AtomicLong count() { - return count; - } - - @Override - public boolean hasNext() { - return count.get() < nbProjects * nbFilesPerProject * nbIssuesPerFile; - } - - @Override - public IssueDoc next() { - IssueDoc issue = new IssueDoc(Maps.newHashMap()); - issue.setKey(Uuids.create()); - issue.setFilePath("src/main/java/Foo" + currentFile); - issue.setComponentUuid("FILE" + currentFile); - issue.setProjectUuid("PROJECT" + currentProject); - issue.setActionPlanKey("PLAN" + currentProject); - issue.setAssignee(users.next()); - issue.setAuthorLogin(users.next()); - issue.setLine(RandomUtils.nextInt()); - issue.setCreationDate(new Date()); - issue.setUpdateDate(new Date()); - issue.setFuncUpdateDate(new Date()); - issue.setFuncCreationDate(new Date()); - issue.setFuncCloseDate(null); - issue.setAttributes(null); - issue.setDebt(1000L); - issue.setEffortToFix(3.14); - issue.setLanguage("php"); - issue.setReporter(users.next()); - issue.setRuleKey(rules.next()); - issue.setResolution(resolutions.next()); - issue.setStatus(statuses.next()); - issue.setSeverity(severities.next()); - issue.setMessage(RandomUtils.nextLong() + "this is the message. Not too short."); - count.incrementAndGet(); - if (count.get() % nbIssuesPerFile == 0) { - currentFile++; - } - if (count.get() % (nbFilesPerProject * nbIssuesPerFile) == 0) { - currentProject++; - } - - return issue; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - private static Iterator cycleIterator(String prefix, int size) { - List values = Lists.newArrayList(); - for (int i = 0; i < size; i++) { - values.add(String.format("%s%d", prefix, i)); - } - return Iterators.cycle(values); - } - - static class ProgressTask extends TimerTask { - public static final long PERIOD_MS = 60000L; - - private final String label; - private final AtomicLong counter; - private long previousCount = 0L; - private long previousTime = 0L; - - public ProgressTask(String label, AtomicLong counter) { - this.label = label; - this.counter = counter; - this.previousTime = System.currentTimeMillis(); - } - - @Override - public void run() { - long currentCount = counter.get(); - long now = System.currentTimeMillis(); - LOGGER.info("{} {} indexed ({} {}/second)", - currentCount, label, documentsPerSecond(currentCount - previousCount, now - previousTime), label); - this.previousCount = currentCount; - this.previousTime = now; - } - } - - static int documentsPerSecond(long nbIssues, long time) { - return (int) Math.round(nbIssues / (time / 1000.0)); - } -} diff --git a/server/sonar-server-benchmark/src/test/resources/logback-test.xml b/server/sonar-server-benchmark/src/test/resources/logback-test.xml deleted file mode 100644 index e595060acc0..00000000000 --- a/server/sonar-server-benchmark/src/test/resources/logback-test.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.3