@@ -0,0 +1,28 @@ | |||
# Definition of QA pipeline at SonarSource | |||
# | |||
# Possible values for SLAVE_TYPE: "performance" (for perf tests) and "gva" (for linux machines connected to DB services) | |||
RUN_ACTIVITY: | |||
- run-db-unit-tests-mysql56 | |||
- run-db-unit-tests-mssql2012 | |||
- run-db-unit-tests-mssql2014 | |||
- run-db-unit-tests-oracle11g | |||
- run-db-unit-tests-oracle12c | |||
- run-db-unit-tests-postgresql93 | |||
exclude: | |||
- RUN_ACTIVITY: run-db-unit-tests-mysql56 | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-db-unit-tests-mssql2012 | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-db-unit-tests-mssql2014 | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-db-unit-tests-oracle11g | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-db-unit-tests-oracle12c | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-db-unit-tests-postgresql93 | |||
SLAVE_TYPE: performance | |||
- RUN_ACTIVITY: run-perf-tests | |||
SLAVE_TYPE: gva |
@@ -4,16 +4,16 @@ install: true | |||
jdk: oraclejdk7 | |||
script: ./travis.sh | |||
env: | |||
- TARGET=CI | |||
- TARGET=IT IT_CATEGORY=Category1 | |||
- TARGET=IT IT_CATEGORY=Category2 | |||
- TARGET=IT IT_CATEGORY=Category3 | |||
- TARGET=IT IT_CATEGORY=Category4 | |||
- TARGET=IT IT_CATEGORY=Plugins | |||
- TARGET=POSTGRES | |||
- TARGET=MYSQL | |||
- TARGET=WEB | |||
#env: | |||
# - TARGET=CI | |||
# - TARGET=IT IT_CATEGORY=Category1 | |||
# - TARGET=IT IT_CATEGORY=Category2 | |||
# - TARGET=IT IT_CATEGORY=Category3 | |||
# - TARGET=IT IT_CATEGORY=Category4 | |||
# - TARGET=IT IT_CATEGORY=Plugins | |||
# - TARGET=POSTGRES | |||
# - TARGET=MYSQL | |||
# - TARGET=WEB | |||
matrix: | |||
@@ -27,9 +27,11 @@ cache: | |||
- 'server/sonar-web/node_modules' | |||
before_cache: | |||
- 'find ~/.m2/repository -type d -name \*-SNAPSHOT -exec rm -rf {} \;' | |||
- 'find ~/.m2/repository -name maven-metadata-\* -exec rm {} \;' | |||
- 'find ~/.m2/repository -name resolver-status.properties -exec rm {} \;' | |||
- 'find $HOME/.m2/repository -type d -name \*-SNAPSHOT -exec rm -rf {} \;' | |||
- 'find $HOME/.m2/repository -name maven-metadata-\* -exec rm {} \;' | |||
- 'find $HOME/.m2/repository -name resolver-status.properties -exec rm {} \;' | |||
# remove all the artifacts (JAR, ZIP) that are installed in local repo because of mvn deploy | |||
- rm -rf $HOME/.m2/repository/org/sonarsource/sonarqube | |||
notifications: | |||
email: false |
@@ -0,0 +1,36 @@ | |||
#!/bin/bash | |||
# | |||
set -euo pipefail | |||
case "$RUN_ACTIVITY" in | |||
run-db-unit-tests-*) | |||
DB_ENGINE=`echo $RUN_ACTIVITY | sed "s/run-db-unit-tests-//g"` | |||
./run-db-unit-tests.sh "http://infra.internal.sonarsource.com/jenkins/orch-${DB_ENGINE}.properties" | |||
;; | |||
run-db-integration-tests-*) | |||
DB_ENGINE=`echo $RUN_ACTIVITY | sed "s/run-db-integration-tests-//g" | cut -d \- -f 1` | |||
CATEGORY=`echo $RUN_ACTIVITY | sed "s/run-db-integration-tests-//g" | cut -d \- -f 2` | |||
echo "./run-db-integration-tests.sh $DB_ENGINE $CATEGORY $SLAVE_TYPE" | |||
;; | |||
run-upgrade-tests-*) | |||
DB_ENGINE=`echo $RUN_ACTIVITY | sed "s/run-upgrade-tests-//g"` | |||
echo "./run-upgrade-tests.sh $DB_ENGINE $SLAVE_TYPE" | |||
;; | |||
run-perf-tests) | |||
./run-perf-tests.sh | |||
;; | |||
*) | |||
echo "unknown RUN_ACTIVITY = $RUN_ACTIVITY" | |||
exit 1 | |||
;; | |||
esac |
@@ -21,19 +21,14 @@ | |||
<dependency> | |||
<groupId>org.sonarsource.orchestrator</groupId> | |||
<artifactId>sonar-orchestrator</artifactId> | |||
<version>3.10.1</version> | |||
<version>${orchestrator.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.sonarsource.sonarqube</groupId> | |||
<artifactId>sonar-xoo-plugin</artifactId> | |||
<version>${project.version}</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.sonarsource.sonarqube</groupId> | |||
<groupId>${project.groupId}</groupId> | |||
<artifactId>sonar-application</artifactId> | |||
<version>${project.version}</version> | |||
<type>zip</type> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
@@ -121,7 +116,7 @@ | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<configuration> | |||
<argLine>-Xmx128m -Dsonar.runtimeVersion=${project.version}</argLine> | |||
<argLine>-Xmx128m -Dsonar.runtimeVersion=${project.version} -Dmaven.localRepository=${settings.localRepository}</argLine> | |||
<skipTests>${skipIts}</skipTests> | |||
<includes> | |||
<include>*/${category}Suite.java</include> | |||
@@ -131,4 +126,77 @@ | |||
</plugins> | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>qa</id> | |||
<activation> | |||
<property> | |||
<name>env.SONARSOURCE_QA</name> | |||
<value>true</value> | |||
</property> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-dependency-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<id>copy-xoo-plugin</id> | |||
<phase>generate-test-resources</phase> | |||
<goals> | |||
<goal>copy</goal> | |||
</goals> | |||
<configuration> | |||
<artifactItems> | |||
<artifactItem> | |||
<groupId>${project.groupId}</groupId> | |||
<artifactId>sonar-xoo-plugin</artifactId> | |||
<version>${project.version}</version> | |||
<type>sonar-plugin</type> | |||
<overWrite>true</overWrite> | |||
</artifactItem> | |||
</artifactItems> | |||
<outputDirectory>../../plugins/sonar-xoo-plugin/target</outputDirectory> | |||
<overWriteReleases>true</overWriteReleases> | |||
<overWriteSnapshots>true</overWriteSnapshots> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
<profile> | |||
<id>with-db-drivers</id> | |||
<activation> | |||
<property> | |||
<name>with-db-drivers</name> | |||
</property> | |||
</activation> | |||
<dependencies> | |||
<dependency> | |||
<groupId>mysql</groupId> | |||
<artifactId>mysql-connector-java</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.postgresql</groupId> | |||
<artifactId>postgresql</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.oracle</groupId> | |||
<artifactId>ojdbc6</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.microsoft.sqljdbc</groupId> | |||
<artifactId>sqljdbc41</artifactId> | |||
<version>4.1</version> | |||
<scope>system</scope> | |||
<systemPath>${project.basedir}/../../sonar-application/src/main/assembly/lib/jdbc/mssql/sqljdbc41.jar | |||
</systemPath> | |||
</dependency> | |||
</dependencies> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -56,13 +56,17 @@ import it.measureHistory.TimeMachineTest; | |||
import it.projectAdministration.BackgroundTasksTest; | |||
import it.projectAdministration.BulkDeletionTest; | |||
import it.projectAdministration.ProjectAdministrationTest; | |||
import it.projectServices.*; | |||
import it.projectServices.AllProjectsTest; | |||
import it.projectServices.ProjectCodeTest; | |||
import it.projectServices.ProjectComparisonTest; | |||
import it.projectServices.ProjectDrilldownTest; | |||
import it.projectServices.ProjectOverviewTest; | |||
import it.projectServices.ProjectWidgetsTest; | |||
import it.qualityGate.QualityGateNotificationTest; | |||
import it.qualityGate.QualityGateTest; | |||
import it.qualityGate.QualityGateUiTest; | |||
import it.settings.PropertySetsTest; | |||
import it.settings.SettingsTest; | |||
import it.settings.SettingsTestRestartingOrchestrator; | |||
import it.settings.SubCategoriesTest; | |||
import it.user.MyAccountPageTest; | |||
import org.junit.ClassRule; | |||
@@ -91,7 +95,6 @@ import static util.ItUtils.xooPlugin; | |||
PropertySetsTest.class, | |||
SubCategoriesTest.class, | |||
SettingsTest.class, | |||
SettingsTestRestartingOrchestrator.class, | |||
// i18n | |||
I18nTest.class, | |||
// quality gate |
@@ -28,11 +28,7 @@ import it.dbCleaner.PurgeTest; | |||
import it.duplication.CrossProjectDuplicationsOnRemoveFileTest; | |||
import it.duplication.CrossProjectDuplicationsTest; | |||
import it.duplication.DuplicationsTest; | |||
import it.serverSystem.HttpsTest; | |||
import it.serverSystem.RestartTest; | |||
import it.serverSystem.ServerSystemRestartingOrchestrator; | |||
import it.serverSystem.ServerSystemTest; | |||
import it.updateCenter.UpdateCenterTest; | |||
import it.user.FavouriteTest; | |||
import it.user.ForceAuthenticationTest; | |||
import org.junit.ClassRule; | |||
@@ -44,18 +40,13 @@ import static util.ItUtils.xooPlugin; | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
// server system | |||
RestartTest.class, | |||
HttpsTest.class, | |||
ServerSystemTest.class, | |||
ServerSystemRestartingOrchestrator.class, | |||
// user | |||
ForceAuthenticationTest.class, | |||
FavouriteTest.class, | |||
// component search | |||
ProjectSearchTest.class, | |||
ComponentsWsTest.class, | |||
// update center | |||
UpdateCenterTest.class, | |||
// analysis exclusion | |||
FileExclusionsTest.class, | |||
IssueExclusionsTest.class, |
@@ -0,0 +1,47 @@ | |||
/* | |||
* 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 it; | |||
import it.serverSystem.HttpsTest; | |||
import it.serverSystem.RestartTest; | |||
import it.serverSystem.ServerSystemRestartingOrchestrator; | |||
import it.settings.SettingsTestRestartingOrchestrator; | |||
import it.updateCenter.UpdateCenterTest; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
/** | |||
* This suite is reserved to the tests that start their own instance of Orchestrator. | |||
* Indeed multiple instances of Orchestrator can't be started in parallel, so this | |||
* suite does not declare a shared Orchestrator. | |||
*/ | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
ServerSystemRestartingOrchestrator.class, | |||
RestartTest.class, | |||
HttpsTest.class, | |||
SettingsTestRestartingOrchestrator.class, | |||
// update center | |||
UpdateCenterTest.class | |||
}) | |||
public class Category5Suite { | |||
} |
@@ -29,7 +29,9 @@ import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import util.selenium.SeleneseTest; | |||
import static util.ItUtils.*; | |||
import static util.ItUtils.pluginArtifact; | |||
import static util.ItUtils.projectDir; | |||
import static util.ItUtils.xooPlugin; | |||
/** | |||
* This class start a new orchestrator on each test case |
@@ -0,0 +1,123 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>org.sonarsource.sonarqube</groupId> | |||
<artifactId>it</artifactId> | |||
<version>5.5-SNAPSHOT</version> | |||
</parent> | |||
<artifactId>perf-tests</artifactId> | |||
<name>SonarQube :: Performance Tests</name> | |||
<properties> | |||
<category>*</category> | |||
</properties> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<configuration> | |||
<argLine>-Dsonar.runtimeVersion=${project.version}</argLine> | |||
<includes> | |||
<include>org/sonarsource/sonarqube/perf/${category}/suite/*TestSuite.java</include> | |||
<!-- not included in suites --> | |||
<include>org/sonarsource/sonarqube/perf/${category}/*Test.java</include> | |||
</includes> | |||
<excludes> | |||
<!-- included into suites --> | |||
<exclude>org/sonarsource/sonarqube/perf/*/suite/*Test.java</exclude> | |||
</excludes> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
<dependencies> | |||
<dependency> | |||
<groupId>${project.groupId}</groupId> | |||
<artifactId>sonar-application</artifactId> | |||
<version>${project.version}</version> | |||
<type>zip</type> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.sonarsource.orchestrator</groupId> | |||
<artifactId>sonar-orchestrator</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.codehaus.sonar</groupId> | |||
<artifactId>sonar-update-center-common</artifactId> | |||
<version>1.12.1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>commons-lang</groupId> | |||
<artifactId>commons-lang</artifactId> | |||
<version>2.6</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<version>4.11</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.kevinsawicki</groupId> | |||
<artifactId>http-request</artifactId> | |||
<version>5.2</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.easytesting</groupId> | |||
<artifactId>fest-assert</artifactId> | |||
<version>1.4</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
<profiles> | |||
<profile> | |||
<id>qa</id> | |||
<activation> | |||
<property> | |||
<name>env.SONARSOURCE_QA</name> | |||
<value>true</value> | |||
</property> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-dependency-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<id>copy-xoo-plugin</id> | |||
<phase>generate-test-resources</phase> | |||
<goals> | |||
<goal>copy</goal> | |||
</goals> | |||
<configuration> | |||
<artifactItems> | |||
<artifactItem> | |||
<groupId>${project.groupId}</groupId> | |||
<artifactId>sonar-xoo-plugin</artifactId> | |||
<version>${project.version}</version> | |||
<type>sonar-plugin</type> | |||
<overWrite>true</overWrite> | |||
</artifactItem> | |||
</artifactItems> | |||
<outputDirectory>../../plugins/sonar-xoo-plugin/target</outputDirectory> | |||
<overWriteReleases>true</overWriteReleases> | |||
<overWriteSnapshots>true</overWriteSnapshots> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
</profiles> | |||
</project> |
@@ -0,0 +1,9 @@ | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>com.sonarsource.it.samples</groupId> | |||
<artifactId>huge-file</artifactId> | |||
<version>1.0-SNAPSHOT</version> | |||
<name>Sonar :: Integration Tests :: Huge File</name> | |||
</project> |
@@ -0,0 +1,6 @@ | |||
sonar.projectKey=sample | |||
sonar.projectName=Sample | |||
sonar.projectVersion=1.0-SNAPSHOT | |||
sonar.sources=src/main/xoo | |||
sonar.tests=src/test/xoo | |||
sonar.language=xoo |
@@ -0,0 +1,12 @@ | |||
package sample; | |||
public class Sample { | |||
public Sample(int i) { | |||
int j = i++; | |||
} | |||
private String myMethod() { | |||
return "hello"; | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
lines:13 | |||
ncloc:13 | |||
#Used by dashboard/widgets tests | |||
complexity_in_classes:3 | |||
classes:1 | |||
comment_lines:0 |
@@ -0,0 +1,21 @@ | |||
package sample; | |||
import org.hamcrest.CoreMatchers; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertThat; | |||
public class SampleTest { | |||
@Test | |||
public void should_return_i() { | |||
Sample sample = new Sample(1); | |||
assertThat(sample.getI(), CoreMatchers.is(1)); | |||
} | |||
@Test | |||
public void should_return_to_string() { | |||
assertThat(new Sample(1).toString(), CoreMatchers.is("1")); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
lines:22 | |||
ncloc:22 | |||
tests:2 | |||
test_execution_time:1 | |||
skipped_tests:0 | |||
test_errors:0 | |||
test_failures:0 |
@@ -0,0 +1,84 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.util.List; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
public class MavenLogs { | |||
/** | |||
* Total time: 6.015s | |||
* Total time: 3:14.025s | |||
*/ | |||
public static Long extractTotalTime(String logs) { | |||
Pattern pattern = Pattern.compile(".*Total time: (\\d*:)?(\\d+).(\\d+)s.*"); | |||
Matcher matcher = pattern.matcher(logs); | |||
if (matcher.matches()) { | |||
String minutes = StringUtils.defaultIfBlank(StringUtils.removeEnd(matcher.group(1), ":"), "0"); | |||
String seconds = StringUtils.defaultIfBlank(matcher.group(2), "0"); | |||
String millis = StringUtils.defaultIfBlank(matcher.group(3), "0"); | |||
return (Long.parseLong(minutes) * 60000) + (Long.parseLong(seconds) * 1000) + Long.parseLong(millis); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Final Memory: 68M/190M | |||
*/ | |||
public static Long extractEndMemory(String logs) { | |||
return extractLong(logs, ".*Final Memory: (\\d+)M/[\\d]+M.*"); | |||
} | |||
public static Long extractMaxMemory(String logs) { | |||
return extractLong(logs, ".*Final Memory: [\\d]+M/(\\d+)M.*"); | |||
} | |||
private static Long extractLong(String logs, String format) { | |||
Pattern pattern = Pattern.compile(format); | |||
Matcher matcher = pattern.matcher(logs); | |||
if (matcher.matches()) { | |||
String s = matcher.group(1); | |||
return Long.parseLong(s); | |||
} | |||
return null; | |||
} | |||
/** | |||
* 2015.09.29 16:57:45 INFO web[o.s.s.c.q.CeWorkerRunnableImpl] Executed task | project=com.github.kevinsawicki:http-request-parent | id=AVAZm9oHIXrp54OmOeQe | time=2283ms | |||
*/ | |||
public static Long extractComputationTotalTime(List<String> logs) { | |||
Pattern pattern = Pattern.compile(".*INFO.*Executed task.* \\| time=(\\d+)ms.*"); | |||
for (int i = logs.size() - 1; i >= 0; i--) { | |||
String line = logs.get(i); | |||
Matcher matcher = pattern.matcher(line); | |||
if (matcher.matches()) { | |||
String duration = matcher.group(1); | |||
return Long.parseLong(duration); | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import org.apache.commons.io.FileUtils; | |||
import java.io.IOException; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import java.util.List; | |||
public class ServerLogs { | |||
static Date extractDate(String line) { | |||
String pattern = "yyyy.MM.dd HH:mm:ss"; | |||
SimpleDateFormat format = new SimpleDateFormat(pattern); | |||
if (line.length() > 19) { | |||
try { | |||
return format.parse(line.substring(0, 19)); | |||
} catch (Exception e) { | |||
// ignore | |||
} | |||
} | |||
return null; | |||
} | |||
public static Date extractFirstDate(List<String> lines) { | |||
for (String line : lines) { | |||
Date d = ServerLogs.extractDate(line); | |||
if (d != null) { | |||
return d; | |||
} | |||
} | |||
return null; | |||
} | |||
public static void clear(Orchestrator orch) throws IOException { | |||
if (orch.getServer() != null && orch.getServer().getLogs() != null) { | |||
FileUtils.write(orch.getServer().getLogs(), "", false); | |||
} | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||
<title>rename_findbugs_profile</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr> | |||
<td rowspan="1" colspan="3">rename_findbugs_profile</td> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/sessions/new</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>type</td> | |||
<td>login</td> | |||
<td>admin</td> | |||
</tr> | |||
<tr> | |||
<td>type</td> | |||
<td>password</td> | |||
<td>admin</td> | |||
</tr> | |||
<tr> | |||
<td>clickAndWait</td> | |||
<td>commit</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>open</td> | |||
<td>/profiles</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>click</td> | |||
<td>id=rename-java_sonar-way-with-findbugs</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>waitForElementPresent</td> | |||
<td>id=new-name</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>type</td> | |||
<td>id=new-name</td> | |||
<td>findbugs-profile</td> | |||
</tr> | |||
<tr> | |||
<td>clickAndWait</td> | |||
<td>id=rename-submit</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>profiles_java</td> | |||
<td>*findbugs-profile*</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</body> | |||
</html> |
@@ -0,0 +1,123 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf; | |||
import com.google.common.base.Joiner; | |||
import org.hamcrest.CustomMatcher; | |||
import org.junit.rules.ErrorCollector; | |||
import org.junit.runner.Description; | |||
import org.junit.runners.model.Statement; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
public abstract class PerfRule extends ErrorCollector { | |||
private final int runCount; | |||
private final List<List<Long>> recordedResults = new ArrayList<List<Long>>(); | |||
private int currentRun; | |||
private String testName; | |||
public PerfRule(int runCount) { | |||
this.runCount = runCount; | |||
} | |||
@Override | |||
public Statement apply(final Statement base, Description description) { | |||
this.testName = description.getMethodName(); | |||
return new Statement() { | |||
@Override | |||
public void evaluate() throws Throwable { | |||
for (currentRun = 1; currentRun <= runCount; currentRun++) { | |||
recordedResults.add(new ArrayList<Long>()); | |||
beforeEachRun(); | |||
base.evaluate(); | |||
} | |||
verify(); | |||
} | |||
}; | |||
} | |||
protected abstract void beforeEachRun(); | |||
public void assertDurationAround(long duration, long expectedDuration) { | |||
currentResults().add(duration); | |||
if (isLastRun()) { | |||
long meanDuration = computeAverageDurationOfCurrentStep(); | |||
double variation = 100.0 * (0.0 + meanDuration - expectedDuration) / expectedDuration; | |||
checkThat(String.format("Expected %d ms in average, got %d ms [%s]", expectedDuration, meanDuration, Joiner.on(",").join(getAllResultsOfCurrentStep())), Math.abs(variation), | |||
new CustomMatcher<Double>( | |||
"a value less than " | |||
+ PerfTestCase.ACCEPTED_DURATION_VARIATION_IN_PERCENTS) { | |||
@Override | |||
public boolean matches(Object item) { | |||
return ((item instanceof Double) && ((Double) item).compareTo(PerfTestCase.ACCEPTED_DURATION_VARIATION_IN_PERCENTS) < 0); | |||
} | |||
}); | |||
} | |||
} | |||
private Long[] getAllResultsOfCurrentStep() { | |||
Long[] result = new Long[runCount]; | |||
for (int i = 0; i < runCount; i++) { | |||
result[i] = recordedResults.get(i).get(currentResults().size() - 1); | |||
} | |||
return result; | |||
} | |||
private long computeAverageDurationOfCurrentStep() { | |||
Long[] result = getAllResultsOfCurrentStep(); | |||
// Compute a truncated mean by ignoring greater value | |||
Arrays.sort(result); | |||
long meanDuration = 0; | |||
for (int i = 0; i < (runCount - 1); i++) { | |||
meanDuration += result[i]; | |||
} | |||
meanDuration /= (runCount - 1); | |||
return meanDuration; | |||
} | |||
private List<Long> currentResults() { | |||
return recordedResults.get(currentRun - 1); | |||
} | |||
public void assertDurationLessThan(long duration, final long maxDuration) { | |||
currentResults().add(duration); | |||
if (isLastRun()) { | |||
long meanDuration = computeAverageDurationOfCurrentStep(); | |||
checkThat(String.format("Expected less than %d ms in average, got %d ms [%s]", maxDuration, meanDuration, Joiner.on(",").join(getAllResultsOfCurrentStep())), meanDuration, | |||
new CustomMatcher<Long>("a value less than " | |||
+ maxDuration) { | |||
@Override | |||
public boolean matches(Object item) { | |||
return ((item instanceof Long) && ((Long) item).compareTo(maxDuration) < 0); | |||
} | |||
}); | |||
} | |||
} | |||
private boolean isLastRun() { | |||
return currentRun == runCount; | |||
} | |||
} |
@@ -0,0 +1,103 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.Properties; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.io.IOUtils; | |||
import org.hamcrest.CustomMatcher; | |||
import org.junit.Rule; | |||
import org.junit.rules.ErrorCollector; | |||
import org.junit.rules.TestName; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public abstract class PerfTestCase { | |||
static final double ACCEPTED_DURATION_VARIATION_IN_PERCENTS = 8.0; | |||
@Rule | |||
public TestName testName = new TestName(); | |||
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 void assertDurationAround(ErrorCollector collector, 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); | |||
collector.checkThat(String.format("Expected %d ms, got %d ms", expectedDuration, duration), Math.abs(variation), new CustomMatcher<Double>("a value less than " | |||
+ ACCEPTED_DURATION_VARIATION_IN_PERCENTS) { | |||
@Override | |||
public boolean matches(Object item) { | |||
return ((item instanceof Double) && ((Double) item).compareTo(ACCEPTED_DURATION_VARIATION_IN_PERCENTS) < 0); | |||
} | |||
}); | |||
} | |||
protected void assertDurationLessThan(long duration, long maxDuration) { | |||
System.out.printf("Test %s : %d ms (max allowed is %d)\n", testName.getMethodName(), duration, maxDuration); | |||
assertThat(duration).as(String.format("Expected less than %d ms, got %d ms", maxDuration, duration)).isLessThanOrEqualTo(maxDuration); | |||
} | |||
protected void assertDurationLessThan(ErrorCollector collector, long duration, final long maxDuration) { | |||
System.out.printf("Test %s : %d ms (max allowed is %d)\n", testName.getMethodName(), duration, maxDuration); | |||
collector.checkThat(String.format("Expected less than %d ms, got %d ms", maxDuration, duration), duration, new CustomMatcher<Long>("a value less than " | |||
+ maxDuration) { | |||
@Override | |||
public boolean matches(Object item) { | |||
return ((item instanceof Long) && ((Long) item).compareTo(maxDuration) < 0); | |||
} | |||
}); | |||
} | |||
protected Properties readProfiling(File baseDir, String moduleKey) throws IOException { | |||
File profilingFile = new File(baseDir, ".sonar/profiling/" + moduleKey + "-profiler.properties"); | |||
Properties props = new Properties(); | |||
FileInputStream in = FileUtils.openInputStream(profilingFile); | |||
try { | |||
props.load(in); | |||
} finally { | |||
IOUtils.closeQuietly(in); | |||
} | |||
return props; | |||
} | |||
/** | |||
* New batch analysis with most features disabled by default (empty QP, no CPD, no SCM, ...) | |||
*/ | |||
public static SonarScanner newScanner(String sonarRunnerOpts, String... props) { | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.scm.disabled", "true", | |||
"sonar.cpd.exclusions", "**") | |||
.setProperties(props); | |||
scanner | |||
.setEnvironmentVariable("SONAR_RUNNER_OPTS", sonarRunnerOpts) | |||
.setProjectDir(FileLocation.of("projects/xoo-sample").getFile()); | |||
return scanner; | |||
} | |||
} |
@@ -0,0 +1,130 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.computation; | |||
import com.google.common.base.Charsets; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import org.sonarsource.sonarqube.perf.MavenLogs; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.junit.Before; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
public class ComputationTest extends PerfTestCase { | |||
private static int MAX_HEAP_SIZE_IN_MEGA = 600; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = Orchestrator | |||
.builderEnv() | |||
.addPlugin(FileLocation.byWildcardMavenFilename(new File("../../plugins/sonar-xoo-plugin/target"), "sonar-xoo-plugin-*.jar")) | |||
.setServerProperty( | |||
"sonar.web.javaOpts", | |||
String.format("-Xms%dm -Xmx%dm -XX:+HeapDumpOnOutOfMemoryError -XX:MaxPermSize=160m -Djava.awt.headless=true", MAX_HEAP_SIZE_IN_MEGA, MAX_HEAP_SIZE_IN_MEGA)) | |||
.setServerProperty("sonar.log.level", "DEBUG") | |||
.restoreProfileAtStartup(FileLocation.ofClasspath("/one-xoo-issue-per-line.xml")) | |||
.build(); | |||
private static File bigProjectBaseDir; | |||
@BeforeClass | |||
public static void classSetUp() throws IOException { | |||
bigProjectBaseDir = createProject(4, 10, 20); | |||
} | |||
@Before | |||
public void before() throws Exception { | |||
orchestrator.resetData(); | |||
} | |||
@Test | |||
public void analyse_big_project() throws Exception { | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "big-project", | |||
"sonar.projectName", "Big Project", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "src", | |||
"sonar.profile", "one-xoo-issue-per-line") | |||
.setProjectDir(bigProjectBaseDir); | |||
orchestrator.executeBuild(scanner); | |||
assertComputationDurationAround(340000L); | |||
} | |||
private void assertComputationDurationAround(long expectedDuration) throws IOException { | |||
File report = new File(orchestrator.getServer().getLogs().getParent(), "sonar.log"); | |||
List<String> logsLines = FileUtils.readLines(report, Charsets.UTF_8); | |||
Long duration = MavenLogs.extractComputationTotalTime(logsLines); | |||
assertDurationAround(duration, expectedDuration); | |||
} | |||
private static File createProject(int dirDepth, int nbDirByLayer, int nbIssuesByFile) throws IOException { | |||
File rootDir = temp.newFolder(); | |||
File projectProperties = new File(rootDir, "sonar-project.properties"); | |||
StringBuilder moduleListBuilder = new StringBuilder(nbDirByLayer * ("module".length() + 2)); | |||
for (int i = 1; i <= nbDirByLayer; i++) { | |||
moduleListBuilder.append("module").append(i); | |||
File moduleDir = new File(rootDir, "module" + i + "/src"); | |||
moduleDir.mkdirs(); | |||
if (i != nbDirByLayer) { | |||
moduleListBuilder.append(","); | |||
} | |||
createProjectFiles(moduleDir, dirDepth - 1, nbDirByLayer, nbIssuesByFile); | |||
} | |||
FileUtils.write(projectProperties, "sonar.modules=", true); | |||
FileUtils.write(projectProperties, moduleListBuilder.toString(), true); | |||
FileUtils.write(projectProperties, "\n", true); | |||
FileUtils.write(projectProperties, "sonar.source=src", true); | |||
return rootDir; | |||
} | |||
private static void createProjectFiles(File dir, int depth, int nbFilesByDir, int nbIssuesByFile) throws IOException { | |||
dir.mkdir(); | |||
for (int i = 1; i <= nbFilesByDir; i++) { | |||
File xooFile = new File(dir, "file" + i + ".xoo"); | |||
String line = xooFile.getAbsolutePath() + i + "\n"; | |||
FileUtils.write(xooFile, StringUtils.repeat(line, nbIssuesByFile)); | |||
File xooMeasureFile = new File(dir, "file" + i + ".xoo.measures"); | |||
FileUtils.write(xooMeasureFile, "lines:" + nbIssuesByFile); | |||
if (depth > 1) { | |||
createProjectFiles(new File(dir, "dir" + i), depth - 1, nbFilesByDir, nbIssuesByFile); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,144 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
// Can't afford multiple executions of this long test, so it does not | |||
// use PerfRule | |||
public class IssuesModeBigTest extends PerfTestCase { | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
private static File baseProjectDir; | |||
@ClassRule | |||
public static final Orchestrator ORCHESTRATOR = Orchestrator | |||
.builderEnv() | |||
.addPlugin(FileLocation.byWildcardMavenFilename(new File("../../plugins/sonar-xoo-plugin/target"), "sonar-xoo-plugin-*.jar")) | |||
// should not be so high, but required as long embedded h2 is used -> requires more memory on server | |||
.setServerProperty("sonar.web.javaOpts", "-Xmx1G -XX:MaxPermSize=100m -XX:+HeapDumpOnOutOfMemoryError") | |||
.restoreProfileAtStartup(FileLocation.ofClasspath("/one-xoo-issue-per-line.xml")) | |||
.build(); | |||
@BeforeClass | |||
public static void setUp() throws Exception { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
// ORCHESTRATOR.executeBuild(PerfTestCase.newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
generateAndScanProject(); | |||
} | |||
@Test | |||
public void issues_mode_scan_big_project() throws IOException { | |||
File userHome = temp.newFolder(); | |||
SonarScanner scanner = createScanner(); | |||
scanner.setProperty("sonar.analysis.mode", "issues"); | |||
scanner.setProperty("sonar.scanAllFiles", "true"); | |||
// Use a new home to start with empty cache | |||
scanner.setProperty("sonar.userHome", userHome.getAbsolutePath()); | |||
long start = System.currentTimeMillis(); | |||
ORCHESTRATOR.executeBuild(scanner); | |||
long firstIssuesDuration = System.currentTimeMillis() - start; | |||
System.out.println("First issues analysis skipping unchanged files: " + firstIssuesDuration + "ms"); | |||
// caches are warmed | |||
start = System.currentTimeMillis(); | |||
ORCHESTRATOR.executeBuild(scanner); | |||
long secondIssuesDuration = System.currentTimeMillis() - start; | |||
System.out.println("Second issues analysis skipping unchanged files: " + secondIssuesDuration + "ms"); | |||
assertDurationAround(secondIssuesDuration, 109_000L); | |||
} | |||
@Test | |||
public void issues_mode_scan_big_project_only_changed() throws IOException { | |||
File userHome = temp.newFolder(); | |||
SonarScanner scanner = createScanner(); | |||
scanner.setProperty("sonar.analysis.mode", "issues"); | |||
// Use a new home to start with empty cache | |||
scanner.setProperty("sonar.userHome", userHome.getAbsolutePath()); | |||
long start = System.currentTimeMillis(); | |||
ORCHESTRATOR.executeBuild(scanner); | |||
long firstIssuesDuration = System.currentTimeMillis() - start; | |||
System.out.println("First issues analysis: " + firstIssuesDuration + "ms"); | |||
// caches are warmed | |||
start = System.currentTimeMillis(); | |||
ORCHESTRATOR.executeBuild(scanner); | |||
long secondIssuesDuration = System.currentTimeMillis() - start; | |||
System.out.println("Second issues analysis: " + secondIssuesDuration + "ms"); | |||
assertDurationAround(secondIssuesDuration, 69_000L); | |||
} | |||
private static void generateAndScanProject() throws IOException { | |||
ORCHESTRATOR.getServer().provisionProject("big", "xoo-big"); | |||
ORCHESTRATOR.getServer().associateProjectToQualityProfile("big", "xoo", "one-xoo-issue-per-line"); | |||
baseProjectDir = generateProject(); | |||
SonarScanner scanner = createScanner(); | |||
long start = System.currentTimeMillis(); | |||
ORCHESTRATOR.executeBuild(scanner); | |||
long firstDuration = System.currentTimeMillis() - start; | |||
System.out.println("Publishing: " + firstDuration + "ms"); | |||
} | |||
private static File generateProject() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
int nbFiles = 100; | |||
int lines = 10000; | |||
for (int nb = 1; nb <= nbFiles; nb++) { | |||
File xooFile = new File(srcDir, "sample" + nb + ".xoo"); | |||
FileUtils.write(xooFile, StringUtils.repeat(StringUtils.repeat("a", 100) + "\n", lines)); | |||
} | |||
return baseDir; | |||
} | |||
private static SonarScanner createScanner() { | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "big", | |||
"sonar.projectName", "xoo-big", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "src", | |||
"sonar.showProfiling", "true"); | |||
scanner | |||
.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx128m -server -XX:MaxPermSize=64m") | |||
.setProjectDir(baseProjectDir); | |||
return scanner; | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner; | |||
import com.google.common.collect.Lists; | |||
import org.sonarsource.sonarqube.perf.MavenLogs; | |||
import org.junit.Test; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public class MavenLogsTest { | |||
@Test | |||
public void testExtractTotalTime() throws Exception { | |||
assertThat(MavenLogs.extractTotalTime(" Total time: 6.015s ")).isEqualTo(6015); | |||
assertThat(MavenLogs.extractTotalTime(" Total time: 3:14.025s ")).isEqualTo(194025); | |||
} | |||
@Test | |||
public void testMaxMemory() throws Exception { | |||
assertThat(MavenLogs.extractMaxMemory(" Final Memory: 68M/190M ")).isEqualTo(190); | |||
} | |||
@Test | |||
public void testEndMemory() throws Exception { | |||
assertThat(MavenLogs.extractEndMemory(" Final Memory: 68M/190M ")).isEqualTo(68); | |||
} | |||
@Test | |||
public void logs_with_different_computations_take_the_last_one() throws Exception { | |||
assertThat(MavenLogs.extractComputationTotalTime(Lists.newArrayList( | |||
"2015.09.29 16:57:45 INFO web[o.s.s.c.q.CeWorkerRunnableImpl] Executed task | project=com.github.kevinsawicki:http-request-parent | id=AVAZm9oHIXrp54OmOeQe | time=2283ms", | |||
"2015.09.29 16:57:45 INFO web[o.s.s.c.q.CeWorkerRunnableImpl] Executed task | project=com.github.kevinsawicki:http-request-parent | id=AVAZm9oHIXrp54OmOeQe | time=1234ms"))) | |||
.isEqualTo(1234L); | |||
} | |||
} |
@@ -0,0 +1,150 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.BuildResult; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import org.sonarsource.sonarqube.perf.MavenLogs; | |||
import org.sonarsource.sonarqube.perf.PerfRule; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Ignore; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
@Ignore("Timeout on computation side") | |||
public class BootstrappingTest extends PerfTestCase { | |||
@Rule | |||
public PerfRule perfRule = new PerfRule(4) { | |||
@Override | |||
protected void beforeEachRun() { | |||
orchestrator.resetData(); | |||
} | |||
}; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
private static File manyFlatModulesBaseDir; | |||
private static File manyNestedModulesBaseDir; | |||
@BeforeClass | |||
public static void setUp() throws IOException { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
orchestrator.executeBuild(newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
manyFlatModulesBaseDir = prepareProjectWithManyFlatModules(100); | |||
manyNestedModulesBaseDir = prepareProjectWithManyNestedModules(50); | |||
} | |||
@Test | |||
public void analyzeProjectWith100FlatModules() throws IOException { | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "many-flat-modules", | |||
"sonar.projectName", "Many Flat Modules", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "", | |||
"sonar.showProfiling", "true"); | |||
scanner | |||
.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx512m -server -XX:MaxPermSize=64m") | |||
.setProjectDir(manyFlatModulesBaseDir); | |||
BuildResult result = orchestrator.executeBuild(scanner); | |||
// First analysis | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 22800L); | |||
result = orchestrator.executeBuild(scanner); | |||
// Second analysis is longer since we load project referential | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 27200L); | |||
} | |||
private static File prepareProjectWithManyFlatModules(int SIZE) throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File projectProps = new File(baseDir, "sonar-project.properties"); | |||
StringBuilder moduleListBuilder = new StringBuilder(SIZE * ("module".length() + 2)); | |||
for (int i = 1; i <= SIZE; i++) { | |||
moduleListBuilder.append("module").append(i); | |||
File moduleDir = new File(baseDir, "module" + i); | |||
moduleDir.mkdir(); | |||
if (i != SIZE) { | |||
moduleListBuilder.append(","); | |||
} | |||
} | |||
FileUtils.write(projectProps, "sonar.modules=", true); | |||
FileUtils.write(projectProps, moduleListBuilder.toString(), true); | |||
FileUtils.write(projectProps, "\n", true); | |||
return baseDir; | |||
} | |||
@Test | |||
public void analyzeProjectWith50NestedModules() throws IOException { | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "many-nested-modules", | |||
"sonar.projectName", "Many Nested Modules", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "", | |||
"sonar.showProfiling", "true"); | |||
scanner.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx512m -server -XX:MaxPermSize=64m"); | |||
scanner.setProjectDir(manyNestedModulesBaseDir); | |||
BuildResult result = orchestrator.executeBuild(scanner); | |||
// First analysis | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 8900L); | |||
result = orchestrator.executeBuild(scanner); | |||
// Second analysis | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 9300L); | |||
} | |||
private static File prepareProjectWithManyNestedModules(int SIZE) throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File currentDir = baseDir; | |||
for (int i = 1; i <= SIZE; i++) { | |||
File projectProps = new File(currentDir, "sonar-project.properties"); | |||
FileUtils.write(projectProps, "sonar.modules=module" + i + "\n", true); | |||
if (i >= 1) { | |||
FileUtils.write(projectProps, "sonar.moduleKey=module" + (i - 1), true); | |||
} | |||
File moduleDir = new File(currentDir, "module" + i); | |||
moduleDir.mkdir(); | |||
currentDir = moduleDir; | |||
} | |||
FileUtils.write(new File(currentDir, "sonar-project.properties"), "sonar.moduleKey=module" + SIZE, true); | |||
return baseDir; | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.MavenBuild; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.IOException; | |||
import org.junit.Before; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ErrorCollector; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.wsclient.services.Resource; | |||
import org.sonar.wsclient.services.ResourceQuery; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public class DuplicationTest extends PerfTestCase { | |||
@Rule | |||
public ErrorCollector collector = new ErrorCollector(); | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
@BeforeClass | |||
public static void setUp() throws IOException { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
orchestrator.executeBuild(newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
} | |||
@Before | |||
public void cleanDatabase() { | |||
orchestrator.resetData(); | |||
} | |||
/** | |||
* SONAR-3060 | |||
*/ | |||
@Test | |||
public void hugeJavaFile() { | |||
MavenBuild build = MavenBuild.create(FileLocation.of("projects/huge-file/pom.xml").getFile()) | |||
.setEnvironmentVariable("MAVEN_OPTS", "-Xmx1024m") | |||
.setProperty("sonar.sourceEncoding", "UTF-8") | |||
.setCleanSonarGoals(); | |||
orchestrator.executeBuild(build); | |||
Resource file = getResource("com.sonarsource.it.samples:huge-file:src/main/java/huge/HugeFile.java"); | |||
assertThat(file.getMeasureValue("duplicated_lines")).isGreaterThan(50000.0); | |||
} | |||
private Resource getResource(String key) { | |||
return orchestrator.getServer().getWsClient() | |||
.find(ResourceQuery.createForMetrics(key, "duplicated_lines", "duplicated_blocks", "duplicated_files", "duplicated_lines_density", "useless-duplicated-lines")); | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.SonarRunner; | |||
import org.sonarsource.sonarqube.perf.PerfRule; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Properties; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.junit.Before; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
public class FileSystemTest extends PerfTestCase { | |||
@Rule | |||
public PerfRule perfRule = new PerfRule(4) { | |||
@Override | |||
protected void beforeEachRun() { | |||
orchestrator.resetData(); | |||
} | |||
}; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
private static File baseDir; | |||
@BeforeClass | |||
public static void setUp() throws IOException { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
orchestrator.executeBuild(newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
baseDir = prepareProject(); | |||
} | |||
@Before | |||
public void cleanDatabase() { | |||
orchestrator.resetData(); | |||
} | |||
@Test | |||
public void indexProjectWith1000BigFilesXmx128() throws IOException { | |||
run(128, 30000L); | |||
} | |||
private void run(int xmx, long expectedDuration) throws IOException { | |||
SonarRunner runner = SonarRunner.create() | |||
.setProperties( | |||
"sonar.projectName", "filesystem xmx" + xmx, | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "src", | |||
"sonar.analysis.mode", "issues", | |||
"sonar.showProfiling", "true") | |||
.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx" + xmx + "m -server -XX:MaxPermSize=64m") | |||
.setProjectDir(baseDir); | |||
orchestrator.executeBuild(runner); | |||
Properties prof = readProfiling(baseDir, "project"); | |||
perfRule.assertDurationAround(Long.valueOf(prof.getProperty("Index filesystem")), expectedDuration); | |||
} | |||
private static File prepareProject() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
int nbFiles = 1000; | |||
int lines = 10000; | |||
for (int nb = 1; nb <= nbFiles; nb++) { | |||
File xooFile = new File(srcDir, "sample" + nb + ".xoo"); | |||
FileUtils.write(xooFile, StringUtils.repeat(StringUtils.repeat("a", 100) + "\n", lines)); | |||
} | |||
return baseDir; | |||
} | |||
} |
@@ -0,0 +1,106 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.BuildResult; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Properties; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.junit.Before; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonarsource.sonarqube.perf.MavenLogs; | |||
import org.sonarsource.sonarqube.perf.PerfRule; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
public class HighlightingTest extends PerfTestCase { | |||
@Rule | |||
public PerfRule perfRule = new PerfRule(4) { | |||
@Override | |||
protected void beforeEachRun() { | |||
orchestrator.resetData(); | |||
} | |||
}; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
@BeforeClass | |||
public static void setUp() throws IOException { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
orchestrator.executeBuild(newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
} | |||
@Before | |||
public void cleanDatabase() { | |||
orchestrator.resetData(); | |||
} | |||
@Test | |||
public void computeSyntaxHighlightingOnBigFiles() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
int nbFiles = 100; | |||
int ruleCount = 100000; | |||
int nblines = 1000; | |||
int linesize = ruleCount / nblines; | |||
for (int nb = 1; nb <= nbFiles; nb++) { | |||
File xooFile = new File(srcDir, "sample" + nb + ".xoo"); | |||
File xoohighlightingFile = new File(srcDir, "sample" + nb + ".xoo.highlighting"); | |||
FileUtils.write(xooFile, StringUtils.repeat(StringUtils.repeat("a", linesize) + "\n", nblines)); | |||
StringBuilder sb = new StringBuilder(16 * ruleCount); | |||
for (int i = 0; i < ruleCount; i++) { | |||
sb.append(i).append(":").append(i + 1).append(":s\n"); | |||
} | |||
FileUtils.write(xoohighlightingFile, sb.toString()); | |||
} | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "highlighting", | |||
"sonar.projectName", "highlighting", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "src", | |||
"sonar.showProfiling", "true"); | |||
scanner.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx512m -server -XX:MaxPermSize=64m") | |||
.setProjectDir(baseDir); | |||
BuildResult result = orchestrator.executeBuild(scanner); | |||
System.out.println("Total time: " + MavenLogs.extractTotalTime(result.getLogs())); | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 28200L); | |||
Properties prof = readProfiling(baseDir, "highlighting"); | |||
perfRule.assertDurationAround(Long.valueOf(prof.getProperty("Xoo Highlighting Sensor")), 10700L); | |||
} | |||
} |
@@ -0,0 +1,98 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.SonarRunner; | |||
import org.sonarsource.sonarqube.perf.PerfRule; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
public class IssuesModeTest extends PerfTestCase { | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@Rule | |||
public PerfRule perfRule = new PerfRule(4) { | |||
@Override | |||
protected void beforeEachRun() { | |||
orchestrator.resetData(); | |||
} | |||
}; | |||
@Before | |||
public void cleanDatabase() { | |||
orchestrator.resetData(); | |||
} | |||
@Test | |||
public void issues_mode_scan_xoo_project() throws IOException { | |||
File userHome = temp.newFolder(); | |||
orchestrator.getServer().provisionProject("sample", "xoo-sample"); | |||
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-xoo-issue-per-line"); | |||
SonarRunner runner = newScanner( | |||
"-Xmx512m -server -XX:MaxPermSize=64m", | |||
"sonar.analysis.mode", "issues", | |||
"sonar.userHome", userHome.getAbsolutePath(), | |||
"sonar.showProfiling", "true"); | |||
long start = System.currentTimeMillis(); | |||
orchestrator.executeBuild(runner); | |||
long duration = System.currentTimeMillis() - start; | |||
System.out.println("Issues analysis: " + duration + "ms"); | |||
perfRule.assertDurationAround(duration, 4450L); | |||
} | |||
@Test | |||
public void issues_mode_with_cache_scan_xoo_project() throws IOException { | |||
File userHome = temp.newFolder(); | |||
orchestrator.getServer().provisionProject("sample", "xoo-sample"); | |||
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-xoo-issue-per-line"); | |||
SonarRunner runner = newScanner( | |||
"-Xmx512m -server -XX:MaxPermSize=64m", | |||
"sonar.analysis.mode", "issues", | |||
"sonar.useWsCache", "true", | |||
"sonar.userHome", userHome.getAbsolutePath(), | |||
"sonar.showProfiling", "true"); | |||
long start = System.currentTimeMillis(); | |||
orchestrator.executeBuild(runner); | |||
long firstDuration = System.currentTimeMillis() - start; | |||
System.out.println("First issues analysis: " + firstDuration + "ms"); | |||
// caches are warmed | |||
start = System.currentTimeMillis(); | |||
orchestrator.executeBuild(runner); | |||
long secondDuration = System.currentTimeMillis() - start; | |||
System.out.println("Second issues analysis: " + secondDuration + "ms"); | |||
perfRule.assertDurationAround(secondDuration, 3350L); | |||
} | |||
} |
@@ -0,0 +1,113 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.google.common.base.Strings; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.BuildResult; | |||
import com.sonar.orchestrator.build.SonarScanner; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.wsclient.services.PropertyCreateQuery; | |||
import org.sonarsource.sonarqube.perf.MavenLogs; | |||
import org.sonarsource.sonarqube.perf.PerfRule; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
public class MemoryTest extends PerfTestCase { | |||
@Rule | |||
public PerfRule perfRule = new PerfRule(4) { | |||
@Override | |||
protected void beforeEachRun() { | |||
orchestrator.resetData(); | |||
} | |||
}; | |||
@ClassRule | |||
public static TemporaryFolder temp = new TemporaryFolder(); | |||
@ClassRule | |||
public static Orchestrator orchestrator = ScannerPerfTestSuite.ORCHESTRATOR; | |||
@Before | |||
public void cleanDatabase() { | |||
orchestrator.resetData(); | |||
} | |||
@Test | |||
public void should_not_fail_with_limited_xmx_memory_and_no_coverage_per_test() { | |||
orchestrator.executeBuild( | |||
newScanner("-Xmx80m -server -XX:-HeapDumpOnOutOfMemoryError")); | |||
} | |||
int DEPTH = 4; | |||
// Property on root module is duplicated in each module so it may be big | |||
@Test | |||
public void analyzeProjectWithManyModulesAndBigProperties() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
prepareModule(baseDir, "moduleA", 1); | |||
prepareModule(baseDir, "moduleB", 1); | |||
prepareModule(baseDir, "moduleC", 1); | |||
FileUtils.write(new File(baseDir, "sonar-project.properties"), "sonar.modules=moduleA,moduleB,moduleC\n", true); | |||
FileUtils.write(new File(baseDir, "sonar-project.properties"), "sonar.myBigProp=" + Strings.repeat("A", 10000), true); | |||
SonarScanner scanner = SonarScanner.create() | |||
.setProperties( | |||
"sonar.projectKey", "big-module-tree", | |||
"sonar.projectName", "Big Module Tree", | |||
"sonar.projectVersion", "1.0", | |||
"sonar.sources", "", | |||
"sonar.showProfiling", "true"); | |||
scanner.setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Xmx512m -server -XX:MaxPermSize=64m") | |||
.setProjectDir(baseDir); | |||
BuildResult result = orchestrator.executeBuild(scanner); | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 5900L); | |||
// Second execution with a property on server side | |||
orchestrator.getServer().getAdminWsClient().create(new PropertyCreateQuery("sonar.anotherBigProp", Strings.repeat("B", 1000), "big-module-tree")); | |||
result = orchestrator.executeBuild(scanner); | |||
perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 5600L); | |||
} | |||
private void prepareModule(File parentDir, String moduleName, int depth) throws IOException { | |||
File moduleDir = new File(parentDir, moduleName); | |||
moduleDir.mkdir(); | |||
File projectProps = new File(moduleDir, "sonar-project.properties"); | |||
FileUtils.write(projectProps, "sonar.moduleKey=" + moduleName + "\n", true); | |||
if (depth < DEPTH) { | |||
FileUtils.write(projectProps, "sonar.modules=" + moduleName + "A," + moduleName + "B," + moduleName + "C\n", true); | |||
prepareModule(moduleDir, moduleName + "A", depth + 1); | |||
prepareModule(moduleDir, moduleName + "B", depth + 1); | |||
prepareModule(moduleDir, moduleName + "C", depth + 1); | |||
} | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.scanner.suite; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
BootstrappingTest.class, | |||
DuplicationTest.class, | |||
FileSystemTest.class, | |||
HighlightingTest.class, | |||
MemoryTest.class, | |||
IssuesModeTest.class | |||
}) | |||
public class ScannerPerfTestSuite { | |||
@ClassRule | |||
public static final Orchestrator ORCHESTRATOR = Orchestrator | |||
.builderEnv() | |||
.addPlugin(FileLocation.byWildcardMavenFilename(new File("../../plugins/sonar-xoo-plugin/target"), "sonar-xoo-plugin-*.jar")) | |||
// should not be so high, but required as long embedded h2 is used -> requires more memory on server | |||
.setServerProperty("sonar.web.javaOpts", "-Xmx1G -XX:MaxPermSize=100m -XX:+HeapDumpOnOutOfMemoryError") | |||
// Needed by DuplicationTest::hugeJavaFile | |||
.setOrchestratorProperty("javaVersion", "LATEST_RELEASE").addPlugin("java") | |||
.restoreProfileAtStartup(FileLocation.ofClasspath("/one-xoo-issue-per-line.xml")) | |||
.build(); | |||
@BeforeClass | |||
public static void setUp() throws IOException { | |||
// Execute a first analysis to prevent any side effects with cache of plugin JAR files | |||
ORCHESTRATOR.executeBuild(PerfTestCase.newScanner("-Xmx512m -server", "sonar.profile", "one-xoo-issue-per-line")); | |||
} | |||
} |
@@ -0,0 +1,84 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.server; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import org.sonarsource.sonarqube.perf.ServerLogs; | |||
import java.io.IOException; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.List; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Test; | |||
public class ServerTest extends PerfTestCase { | |||
// ES + TOMCAT | |||
@Test | |||
public void server_startup_and_shutdown() throws Exception { | |||
String defaultWebJavaOptions = "-Xmx768m -XX:MaxPermSize=160m -XX:+HeapDumpOnOutOfMemoryError -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.management.enabled=false"; | |||
Orchestrator orchestrator = Orchestrator.builderEnv() | |||
.setOrchestratorProperty("javaVersion", "LATEST_RELEASE") | |||
.addPlugin("java") | |||
// See http://wiki.apache.org/tomcat/HowTo/FasterStartUp | |||
// Sometimes source of entropy is too small and Tomcat spends ~20 seconds on the step : | |||
// "Creation of SecureRandom instance for session ID generation using [SHA1PRNG]" | |||
// Using /dev/urandom fixes the issue on linux | |||
.setServerProperty("sonar.web.javaOpts", defaultWebJavaOptions + " -Djava.security.egd=file:/dev/./urandom") | |||
.build(); | |||
try { | |||
long startupDuration = start(orchestrator); | |||
assertDurationAround(startupDuration, 46000); | |||
long shutdownDuration = stop(orchestrator); | |||
// can't use percent margins because logs are second-grained but not milliseconds | |||
assertDurationLessThan(shutdownDuration, 4000); | |||
} finally { | |||
orchestrator.stop(); | |||
} | |||
} | |||
long start(Orchestrator orchestrator) throws IOException { | |||
ServerLogs.clear(orchestrator); | |||
orchestrator.start(); | |||
return logsPeriod(orchestrator); | |||
} | |||
long stop(Orchestrator orchestrator) throws Exception { | |||
ServerLogs.clear(orchestrator); | |||
orchestrator.stop(); | |||
return logsPeriod(orchestrator); | |||
} | |||
private long logsPeriod(Orchestrator orchestrator) throws IOException { | |||
// compare dates of first and last log | |||
List<String> lines = FileUtils.readLines(orchestrator.getServer().getLogs()); | |||
if (lines.size() < 2) { | |||
throw new IllegalStateException("Fail to estimate server shutdown or startup duration. Not enough logs."); | |||
} | |||
Date start = ServerLogs.extractFirstDate(lines); | |||
Collections.reverse(lines); | |||
Date end = ServerLogs.extractFirstDate(lines); | |||
return end.getTime() - start.getTime(); | |||
} | |||
} |
@@ -0,0 +1,187 @@ | |||
/* | |||
* 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.sonarsource.sonarqube.perf.server; | |||
import com.github.kevinsawicki.http.HttpRequest; | |||
import com.sonar.orchestrator.Orchestrator; | |||
import com.sonar.orchestrator.build.MavenBuild; | |||
import com.sonar.orchestrator.locator.FileLocation; | |||
import org.junit.Ignore; | |||
import org.sonarsource.sonarqube.perf.PerfTestCase; | |||
import org.junit.BeforeClass; | |||
import org.junit.ClassRule; | |||
import org.junit.Test; | |||
import static org.junit.Assert.fail; | |||
@Ignore("Temporarily disabled as it requires access to IT_SOURCES") | |||
public class WebTest extends PerfTestCase { | |||
static final int DEFAULT_PAGE_TIMEOUT_MS = 1000; | |||
@ClassRule | |||
public static Orchestrator orchestrator = Orchestrator.builderEnv() | |||
.setOrchestratorProperty("javaVersion", "LATEST_RELEASE") | |||
.addPlugin("java") | |||
.restoreProfileAtStartup(FileLocation.ofClasspath("/java-quality-profile.xml")) | |||
.build(); | |||
@BeforeClass | |||
public static void scan_struts() throws Exception { | |||
FileLocation strutsHome = orchestrator.getFileLocationOfShared("it-sonar-performancing/struts-1.3.9/pom.xml"); | |||
MavenBuild scan = MavenBuild.create(strutsHome.getFile()); | |||
scan.setGoals("sonar:sonar -V"); | |||
scan.setEnvironmentVariable("MAVEN_OPTS", "-Xmx512m -server"); | |||
scan.setProperty("sonar.scm.disabled", "true"); | |||
scan.setProperty("sonar.sourceEncoding", "UTF-8"); | |||
orchestrator.executeBuild(scan); | |||
} | |||
@Test | |||
public void homepage() throws Exception { | |||
PageStats counters = request("/"); | |||
assertDurationLessThan(counters.durationMs, 300); | |||
} | |||
@Test | |||
public void quality_profiles() throws Exception { | |||
PageStats counters = request("/profiles"); | |||
assertDurationLessThan(counters.durationMs, DEFAULT_PAGE_TIMEOUT_MS); | |||
} | |||
@Test | |||
public void issues_search() throws Exception { | |||
PageStats counters = request("/issues/search"); | |||
assertDurationLessThan(counters.durationMs, 300); | |||
} | |||
@Test | |||
public void measures_search() throws Exception { | |||
PageStats counters = request("/measures"); | |||
assertDurationLessThan(counters.durationMs, 550); | |||
} | |||
@Test | |||
public void all_projects() throws Exception { | |||
PageStats counters = request("/all_projects?qualifier=TRK"); | |||
assertDurationLessThan(counters.durationMs, 300); | |||
} | |||
@Test | |||
public void project_measures_search() throws Exception { | |||
PageStats counters = request("/measures/search?qualifiers[]=TRK"); | |||
assertDurationLessThan(counters.durationMs, 300); | |||
} | |||
@Test | |||
public void file_measures_search() throws Exception { | |||
PageStats counters = request("/measures/search?qualifiers[]=FIL"); | |||
assertDurationLessThan(counters.durationMs, 500); | |||
} | |||
@Test | |||
public void struts_dashboard() throws Exception { | |||
PageStats counters = request("/dashboard/index/org.apache.struts:struts-parent?name=Custom"); | |||
assertDurationLessThan(counters.durationMs, 400); | |||
} | |||
@Test | |||
public void struts_issues() throws Exception { | |||
PageStats counters = request("/issues/search?componentRoots=org.apache.struts:struts-parent"); | |||
assertDurationLessThan(counters.durationMs, 300); | |||
} | |||
@Test | |||
public void struts_issues_drilldown() throws Exception { | |||
PageStats counters = request("/drilldown/issues/org.apache.struts:struts-parent"); | |||
assertDurationLessThan(counters.durationMs, 400); | |||
} | |||
@Test | |||
public void struts_measures_drilldown() throws Exception { | |||
PageStats counters = request("/drilldown/measures/org.apache.struts:struts-parent?metric=ncloc"); | |||
// sounds too high ! | |||
assertDurationLessThan(counters.durationMs, DEFAULT_PAGE_TIMEOUT_MS); | |||
} | |||
@Test | |||
public void struts_debt_overview() throws Exception { | |||
PageStats counters = request("/overview/issues?id=org.apache.struts:struts-parent"); | |||
assertDurationLessThan(counters.durationMs, DEFAULT_PAGE_TIMEOUT_MS); | |||
} | |||
@Test | |||
public void stylesheet_file() throws Exception { | |||
PageStats counters = request("/css/sonar.css"); | |||
assertDurationLessThan(counters.durationMs, 40); | |||
} | |||
@Test | |||
public void javascript_file() throws Exception { | |||
PageStats counters = request("/js/bundles/sonar.js"); | |||
assertDurationLessThan(counters.durationMs, 40); | |||
} | |||
PageStats request(String path) { | |||
String url = orchestrator.getServer().getUrl() + path; | |||
// warm-up | |||
for (int i = 0; i < 5; i++) { | |||
newRequest(url).code(); | |||
} | |||
long targetDuration = Long.MAX_VALUE; | |||
long targetSize = 0L; | |||
for (int i = 0; i < 10; i++) { | |||
HttpRequest request = newRequest(url); | |||
long start = System.currentTimeMillis(); | |||
if (request.ok()) { | |||
long duration = System.currentTimeMillis() - start; | |||
int size = request.body().length(); | |||
if (duration < targetDuration) { | |||
targetDuration = duration; | |||
targetSize = size; | |||
} | |||
System.out.printf("##### Page %50s %7d ms %7d bytes\n", path, duration, size); | |||
} | |||
} | |||
if (targetDuration == Long.MAX_VALUE) { | |||
fail(String.format("Failed to load page: %s", url)); | |||
} | |||
return new PageStats(targetDuration, targetSize); | |||
} | |||
private HttpRequest newRequest(String url) { | |||
HttpRequest request = HttpRequest.get(url); | |||
request.followRedirects(false).acceptJson().acceptCharset(HttpRequest.CHARSET_UTF8); | |||
return request; | |||
} | |||
static class PageStats { | |||
long durationMs; | |||
long sizeBytes; | |||
PageStats(long durationMs, long sizeBytes) { | |||
this.durationMs = durationMs; | |||
this.sizeBytes = sizeBytes; | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar --> | |||
<profile> | |||
<name>one-xoo-issue-per-line</name> | |||
<language>xoo</language> | |||
<rules> | |||
<rule> | |||
<repositoryKey>xoo</repositoryKey> | |||
<key>OneIssuePerLine</key> | |||
<priority>MAJOR</priority> | |||
</rule> | |||
</rules> | |||
</profile> |
@@ -15,7 +15,10 @@ | |||
<properties> | |||
<maven.deploy.skip>true</maven.deploy.skip> | |||
<source.skip>true</source.skip> | |||
<enforcer.skip>true</enforcer.skip> | |||
</properties> | |||
<modules> | |||
<module>it-plugins</module> | |||
<module>it-tests</module> |
@@ -66,6 +66,7 @@ | |||
<slf4j.version>1.7.12</slf4j.version> | |||
<tomcat.version>8.0.30</tomcat.version> | |||
<elasticsearch.version>1.7.2</elasticsearch.version> | |||
<orchestrator.version>3.11-build315</orchestrator.version> | |||
<okhttp.version>2.6.0</okhttp.version> | |||
<protobuf.version>3.0.0-beta-1</protobuf.version> | |||
@@ -737,6 +738,11 @@ | |||
<artifactId>mysql-connector-java</artifactId> | |||
<version>5.1.35</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.oracle</groupId> | |||
<artifactId>ojdbc6</artifactId> | |||
<version>11.2.0.4.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.postgresql</groupId> | |||
<artifactId>postgresql</artifactId> |
@@ -0,0 +1,12 @@ | |||
#!/bin/bash | |||
set -euo pipefail | |||
ORCHESTRATOR_CONFIG_URL=$1 | |||
shift | |||
cd it | |||
mvn verify \ | |||
-Dorchestrator.configUrl=$ORCHESTRATOR_CONFIG_URL \ | |||
-Dwith-db-drivers \ | |||
-Dcategory=Category1 \ | |||
-Dsource.skip=true -B -e -V $* |
@@ -0,0 +1,11 @@ | |||
#!/bin/bash | |||
set -euo pipefail | |||
ORCHESTRATOR_CONFIG_URL=$1 | |||
shift | |||
mvn verify \ | |||
-pl :sonar-db \ | |||
-Dorchestrator.configUrl=$ORCHESTRATOR_CONFIG_URL \ | |||
-Dwith-db-drivers \ | |||
-B -e -V $* |
@@ -0,0 +1,6 @@ | |||
#!/bin/bash | |||
set -euo pipefail | |||
echo 'Run performance tests' | |||
cd it/perf-tests | |||
mvn verify -B -e -V $* |
@@ -1,5 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
@@ -139,12 +140,60 @@ | |||
</build> | |||
<profiles> | |||
<profile> | |||
<id>create-db</id> | |||
<activation> | |||
<property> | |||
<name>env.SONARSOURCE_QA</name> | |||
<value>true</value> | |||
</property> | |||
</activation> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-dependency-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<id>download-sq</id> | |||
<goals> | |||
<goal>get</goal> | |||
</goals> | |||
<phase>generate-test-resources</phase> | |||
<configuration> | |||
<artifact>${project.groupId}:sonar-application:${project.version}:zip</artifact> | |||
<transitive>false</transitive> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.sonarsource.orchestrator</groupId> | |||
<artifactId>orchestrator-maven-plugin</artifactId> | |||
<version>${orchestrator.version}</version> | |||
<executions> | |||
<execution> | |||
<id>create-db</id> | |||
<goals> | |||
<goal>create-db</goal> | |||
</goals> | |||
<phase>generate-test-resources</phase> | |||
<configuration> | |||
<sqVersion>${project.version}</sqVersion> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</profile> | |||
<profile> | |||
<!-- SonarSource internal use --> | |||
<id>dbTests</id> | |||
<id>with-db-drivers</id> | |||
<activation> | |||
<property> | |||
<name>dbTests</name> | |||
<name>with-db-drivers</name> | |||
</property> | |||
</activation> | |||
<properties> | |||
@@ -160,18 +209,16 @@ | |||
<artifactId>postgresql</artifactId> | |||
</dependency> | |||
<dependency> | |||
<!-- this artifact is located in the SonarSource internal repository --> | |||
<groupId>com.oracle</groupId> | |||
<artifactId>ojdbc6</artifactId> | |||
<version>11.2.0.3.0</version> | |||
<scope>test</scope> | |||
<groupId>com.oracle</groupId> | |||
<artifactId>ojdbc6</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.microsoft.sqljdbc</groupId> | |||
<artifactId>sqljdbc41</artifactId> | |||
<version>4.1</version> | |||
<scope>system</scope> | |||
<systemPath>${project.basedir}/../sonar-application/src/main/assembly/lib/jdbc/mssql/sqljdbc41.jar</systemPath> | |||
<systemPath>${project.basedir}/../sonar-application/src/main/assembly/lib/jdbc/mssql/sqljdbc41.jar | |||
</systemPath> | |||
</dependency> | |||
</dependencies> | |||
</profile> |
@@ -185,27 +185,31 @@ public abstract class DatabaseCommands { | |||
} | |||
public void resetPrimaryKeys(DataSource dataSource) throws SQLException { | |||
Connection connection = dataSource.getConnection(); | |||
connection.setAutoCommit(false); | |||
Statement statement = connection.createStatement(); | |||
for (String table : DatabaseVersion.TABLES) { | |||
try { | |||
ResultSet result = statement.executeQuery("SELECT CASE WHEN MAX(ID) IS NULL THEN 1 ELSE MAX(ID)+1 END FROM " + table); | |||
result.next(); | |||
int maxId = result.getInt(1); | |||
result.close(); | |||
for (String resetCommand : resetSequenceSql(table, maxId)) { | |||
statement.executeUpdate(resetCommand); | |||
Connection connection = null; | |||
Statement statement = null; | |||
ResultSet resultSet = null; | |||
try { | |||
connection = dataSource.getConnection(); | |||
connection.setAutoCommit(false); | |||
statement = connection.createStatement(); | |||
for (String table : DatabaseVersion.TABLES) { | |||
try { | |||
resultSet = statement.executeQuery("SELECT CASE WHEN MAX(ID) IS NULL THEN 1 ELSE MAX(ID)+1 END FROM " + table); | |||
resultSet.next(); | |||
int maxId = resultSet.getInt(1); | |||
resultSet.close(); | |||
for (String resetCommand : resetSequenceSql(table, maxId)) { | |||
statement.executeUpdate(resetCommand); | |||
} | |||
connection.commit(); | |||
} catch (Exception e) { | |||
connection.rollback(); // this table has no primary key | |||
} | |||
connection.commit(); | |||
} catch (Exception e) { | |||
connection.rollback(); // this table has no primary key | |||
} | |||
} finally { | |||
DbUtils.closeQuietly(connection, statement, resultSet); | |||
} | |||
statement.close(); | |||
connection.close(); | |||
} | |||
} |
@@ -120,11 +120,10 @@ public class FeedFileSourcesTest { | |||
try { | |||
connection = db.openConnection(); | |||
connection.prepareStatement("insert into snapshot_sources " + | |||
db.executeUpdateSql("insert into snapshot_sources " + | |||
"(snapshot_id, data, updated_at) " + | |||
"values " + | |||
"(6, 'class Foo {\r\n // Empty\r\n}\r\n', '2014-10-31 16:44:02.000')") | |||
.executeUpdate(); | |||
"(6, 'class Foo {\r\n // Empty\r\n}\r\n', '2014-10-31 16:44:02.000')"); | |||
db.executeUpdateSql("insert into snapshot_sources " + | |||
"(snapshot_id, data, updated_at) " + | |||
@@ -137,6 +136,7 @@ public class FeedFileSourcesTest { | |||
"(1, 6, ?)"); | |||
revisionStmt.setBytes(1, "1=aef12a;2=abe465;3=afb789;4=afb789".getBytes(StandardCharsets.UTF_8)); | |||
revisionStmt.executeUpdate(); | |||
revisionStmt.close(); | |||
PreparedStatement authorStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -144,6 +144,7 @@ public class FeedFileSourcesTest { | |||
"(2, 6, ?)"); | |||
authorStmt.setBytes(1, "1=alice;2=bob;3=carol;4=carol".getBytes(StandardCharsets.UTF_8)); | |||
authorStmt.executeUpdate(); | |||
authorStmt.close(); | |||
PreparedStatement dateStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -151,6 +152,7 @@ public class FeedFileSourcesTest { | |||
"(3, 6, ?)"); | |||
dateStmt.setBytes(1, "1=2014-04-25T12:34:56+0100;2=2014-07-25T12:34:56+0100;3=2014-03-23T12:34:56+0100;4=2014-03-23T12:34:56+0100".getBytes(StandardCharsets.UTF_8)); | |||
dateStmt.executeUpdate(); | |||
dateStmt.close(); | |||
PreparedStatement utHitsStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -158,6 +160,7 @@ public class FeedFileSourcesTest { | |||
"(4, 6, ?)"); | |||
utHitsStmt.setBytes(1, "1=1;3=0".getBytes(StandardCharsets.UTF_8)); | |||
utHitsStmt.executeUpdate(); | |||
utHitsStmt.close(); | |||
PreparedStatement utCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -165,6 +168,7 @@ public class FeedFileSourcesTest { | |||
"(5, 6, ?)"); | |||
utCondStmt.setBytes(1, "1=4".getBytes(StandardCharsets.UTF_8)); | |||
utCondStmt.executeUpdate(); | |||
utCondStmt.close(); | |||
PreparedStatement utCoveredCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -172,6 +176,7 @@ public class FeedFileSourcesTest { | |||
"(6, 6, ?)"); | |||
utCoveredCondStmt.setBytes(1, "1=2".getBytes(StandardCharsets.UTF_8)); | |||
utCoveredCondStmt.executeUpdate(); | |||
utCoveredCondStmt.close(); | |||
PreparedStatement itHitsStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -179,6 +184,7 @@ public class FeedFileSourcesTest { | |||
"(7, 6, ?)"); | |||
itHitsStmt.setBytes(1, "1=2;3=0".getBytes(StandardCharsets.UTF_8)); | |||
itHitsStmt.executeUpdate(); | |||
itHitsStmt.close(); | |||
PreparedStatement itCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -186,6 +192,7 @@ public class FeedFileSourcesTest { | |||
"(8, 6, ?)"); | |||
itCondStmt.setBytes(1, "1=5".getBytes(StandardCharsets.UTF_8)); | |||
itCondStmt.executeUpdate(); | |||
itCondStmt.close(); | |||
PreparedStatement itCoveredCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -193,6 +200,7 @@ public class FeedFileSourcesTest { | |||
"(9, 6, ?)"); | |||
itCoveredCondStmt.setBytes(1, "1=3".getBytes(StandardCharsets.UTF_8)); | |||
itCoveredCondStmt.executeUpdate(); | |||
itCoveredCondStmt.close(); | |||
PreparedStatement overallHitsStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -200,6 +208,7 @@ public class FeedFileSourcesTest { | |||
"(10, 6, ?)"); | |||
overallHitsStmt.setBytes(1, "1=3;3=0".getBytes(StandardCharsets.UTF_8)); | |||
overallHitsStmt.executeUpdate(); | |||
overallHitsStmt.close(); | |||
PreparedStatement overallCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -207,6 +216,7 @@ public class FeedFileSourcesTest { | |||
"(11, 6, ?)"); | |||
overallCondStmt.setBytes(1, "1=6".getBytes(StandardCharsets.UTF_8)); | |||
overallCondStmt.executeUpdate(); | |||
overallCondStmt.close(); | |||
PreparedStatement overallCoveredCondStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -214,6 +224,7 @@ public class FeedFileSourcesTest { | |||
"(12, 6, ?)"); | |||
overallCoveredCondStmt.setBytes(1, "1=4".getBytes(StandardCharsets.UTF_8)); | |||
overallCoveredCondStmt.executeUpdate(); | |||
overallCoveredCondStmt.close(); | |||
PreparedStatement duplicationDataStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, " + columnName + ") " + | |||
@@ -225,6 +236,7 @@ public class FeedFileSourcesTest { | |||
"<duplications><g><b s=\"1\" l=\"1\" r=\"MyProject:src/main/xoo/prj/MyFile.xoo\"/><b s=\"2\" l=\"1\" r=\"MyProject:src/main/xoo/prj/MyFile.xoo\"/><b s=\"3\" l=\"1\" r=\"MyProject:src/main/xoo/prj/AnotherFile.xoo\"/></g></duplications>" | |||
.getBytes(StandardCharsets.UTF_8)); | |||
duplicationDataStmt.executeUpdate(); | |||
duplicationDataStmt.close(); | |||
} finally { | |||
DbUtils.commitAndCloseQuietly(connection); | |||
} | |||
@@ -259,6 +271,7 @@ public class FeedFileSourcesTest { | |||
db.prepareDbUnit(getClass(), "before.xml"); | |||
Connection connection = null; | |||
PreparedStatement duplicationDataStmt = null; | |||
try { | |||
connection = db.openConnection(); | |||
@@ -273,7 +286,7 @@ public class FeedFileSourcesTest { | |||
"values " + | |||
"(7, '', '2014-10-31 16:44:02.000')"); | |||
PreparedStatement duplicationDataStmt = connection.prepareStatement("insert into project_measures " + | |||
duplicationDataStmt = connection.prepareStatement("insert into project_measures " + | |||
"(metric_id, snapshot_id, text_value) " + | |||
"values " + | |||
"(13, 6, ?)"); | |||
@@ -284,6 +297,7 @@ public class FeedFileSourcesTest { | |||
.getBytes(StandardCharsets.UTF_8)); | |||
duplicationDataStmt.executeUpdate(); | |||
} finally { | |||
DbUtils.close(duplicationDataStmt); | |||
DbUtils.commitAndCloseQuietly(connection); | |||
} | |||
@@ -4,7 +4,7 @@ set -euo pipefail | |||
function configureTravis { | |||
mkdir ~/.local | |||
curl -sSL https://github.com/SonarSource/travis-utils/tarball/v24 | tar zx --strip-components 1 -C ~/.local | |||
curl -sSL https://github.com/SonarSource/travis-utils/tarball/v25 | tar zx --strip-components 1 -C ~/.local | |||
source ~/.local/bin/install | |||
} | |||
configureTravis | |||
@@ -28,7 +28,7 @@ CI) | |||
-Pdeploy-sonarsource \ | |||
-B -e -V | |||
elif [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ -n "${GITHUB_TOKEN-}" ]; then | |||
elif [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ -n "${GITHUB_TOKEN:-}" ]; then | |||
strongEcho 'Build and analyze pull request, no deploy' | |||
# No need for Maven phase "install" as the generated JAR file does not need to be installed | |||
@@ -57,21 +57,6 @@ CI) | |||
fi | |||
;; | |||
POSTGRES) | |||
psql -c 'create database sonar;' -U postgres | |||
runDatabaseCI "postgresql" "jdbc:postgresql://localhost/sonar" "postgres" "" | |||
;; | |||
MYSQL) | |||
mysql -e "CREATE DATABASE sonar CHARACTER SET UTF8;" -uroot | |||
mysql -e "CREATE USER 'sonar'@'localhost' IDENTIFIED BY 'sonar';" -uroot | |||
mysql -e "GRANT ALL ON sonar.* TO 'sonar'@'localhost';" -uroot | |||
mysql -e "FLUSH PRIVILEGES;" -uroot | |||
runDatabaseCI "mysql" "jdbc:mysql://localhost/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance" "sonar" "sonar" | |||
;; | |||
WEB) | |||
set +eu | |||
source ~/.nvm/nvm.sh && nvm install 4 | |||
@@ -80,11 +65,10 @@ WEB) | |||
;; | |||
IT) | |||
if [ "$IT_CATEGORY" == "Plugins" ] && [ ! -n "$GITHUB_TOKEN" ]; then | |||
if [ "$IT_CATEGORY" == "Plugins" ] && [ ! -n "${GITHUB_TOKEN:-}" ]; then | |||
echo "This job is ignored as it needs to access a private GitHub repository" | |||
else | |||
start_xvfb | |||
mvn install -Pit,dev -DskipTests -Dcategory=$IT_CATEGORY -Dmaven.test.redirectTestOutputToFile=false -B -V -e -Dsource.skip=true | |||
fi | |||
;; |