Skip to content

Commit

Permalink
SONAR-6817 Issues mode should support analysis of projects not associ…
Browse files Browse the repository at this point in the history
…ated
  • Loading branch information
dbmeneses committed Sep 9, 2015
1 parent 84c39f5 commit 4be016e
Show file tree
Hide file tree
Showing 77 changed files with 2,076 additions and 598 deletions.
@@ -0,0 +1,5 @@
#sonar.projectKey=sample
sonar.projectName=Sample
sonar.projectVersion=1.0-SNAPSHOT
sonar.sources=src/main/xoo
sonar.language=xoo
@@ -0,0 +1,16 @@
package sample;

public class Sample {

public Sample(int i) {
int j = i++;
}

private String myMethod() {
if (foo == bar) {
return "hello";
} else {
throw new IllegalStateException();
}
}
}
@@ -0,0 +1,11 @@
ncloc:13
#Used by dashboard/widgets tests
complexity:3
complexity_in_classes:3
classes:1
comment_lines:3
public_api:5
public_undocumented_api:2
duplicated_files:1
duplicated_blocks:2
duplicated_lines:3
43 changes: 33 additions & 10 deletions it/it-tests/src/test/java/batch/IssuesModeTest.java
Expand Up @@ -69,28 +69,45 @@ public void deleteData() throws IOException {
} }


@Test @Test
public void issuesAnalysisOnNewProject() throws IOException { public void issues_analysis_on_new_project() throws IOException {
restoreProfile("one-issue-per-line.xml"); restoreProfile("one-issue-per-line.xml");
orchestrator.getServer().provisionProject("sample", "xoo-sample"); orchestrator.getServer().provisionProject("sample", "xoo-sample");
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line"); orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
SonarRunner runner = configureRunnerIssues("shared/xoo-sample"); SonarRunner runner = configureRunnerIssues("shared/xoo-sample");
orchestrator.executeBuild(runner); BuildResult result = orchestrator.executeBuild(runner);
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
} }

@Test @Test
public void invalidIncrementalMode() throws IOException { public void invalid_incremental_mode() throws IOException {
restoreProfile("one-issue-per-line.xml"); restoreProfile("one-issue-per-line.xml");
orchestrator.getServer().provisionProject("sample", "xoo-sample"); orchestrator.getServer().provisionProject("sample", "xoo-sample");
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line"); orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
SonarRunner runner = configureRunner("shared/xoo-sample"); SonarRunner runner = configureRunner("shared/xoo-sample");
runner.setProperty("sonar.analysis.mode", "incremental"); runner.setProperty("sonar.analysis.mode", "incremental");

thrown.expect(BuildFailureException.class); thrown.expect(BuildFailureException.class);
BuildResult res = orchestrator.executeBuild(runner); BuildResult res = orchestrator.executeBuild(runner);

assertThat(res.getLogs()).contains("Invalid analysis mode: incremental. This mode was removed in SonarQube 5.2"); assertThat(res.getLogs()).contains("Invalid analysis mode: incremental. This mode was removed in SonarQube 5.2");
} }


@Test
public void non_associated_mode() throws IOException {
restoreProfile("one-issue-per-line.xml");
setDefaultQualityProfile("xoo", "one-issue-per-line");
SonarRunner runner = configureRunnerIssues("shared/xoo-sample-non-associated");
BuildResult result = orchestrator.executeBuild(runner);

assertThat(result.getLogs()).contains("is not associated");
assertThat(result.getLogs()).contains("Cache not found, synchronizing data");
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);

result = orchestrator.executeBuild(runner);
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
assertThat(result.getLogs()).contains("Found cache");
}

// SONAR-5715 // SONAR-5715
@Test @Test
public void test_issues_mode_on_project_with_space_in_filename() throws IOException { public void test_issues_mode_on_project_with_space_in_filename() throws IOException {
Expand Down Expand Up @@ -329,16 +346,16 @@ public BuildResult call() throws Exception {
boolean expectedError = false; boolean expectedError = false;
for (Future<BuildResult> result : executorService.invokeAll(tasks)) { for (Future<BuildResult> result : executorService.invokeAll(tasks)) {
try { try {
result.get(); result.get();
} catch(ExecutionException e) { } catch (ExecutionException e) {
if(e.getCause() instanceof BuildFailureException) { if (e.getCause() instanceof BuildFailureException) {
BuildFailureException bfe = (BuildFailureException) e.getCause(); BuildFailureException bfe = (BuildFailureException) e.getCause();
assertThat(bfe.getResult().getLogs()).contains("Another SonarQube analysis is already in progress for this project"); assertThat(bfe.getResult().getLogs()).contains("Another SonarQube analysis is already in progress for this project");
expectedError = true; expectedError = true;
} }
} }
} }
if(!expectedError) { if (!expectedError) {
fail("At least one of the threads should have failed"); fail("At least one of the threads should have failed");
} }
} }
Expand Down Expand Up @@ -370,4 +387,10 @@ private SonarRunner configureRunner(String projectDir, String... props) throws I
return runner; return runner;
} }


private void setDefaultQualityProfile(String languageKey, String profileName) {
orchestrator.getServer().adminWsClient().post("api/qualityprofiles/set_default",
"language", languageKey,
"profileName", profileName);
}

} }
Expand Up @@ -45,6 +45,10 @@ public class ProjectRepositories {
public Map<String, String> settings(String moduleKey) { public Map<String, String> settings(String moduleKey) {
return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap(); return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap();
} }

public Map<String, Map<String, String>> settings() {
return settingsByModule;
}


public ProjectRepositories addSettings(String moduleKey, Map<String, String> settings) { public ProjectRepositories addSettings(String moduleKey, Map<String, String> settings) {
Map<String, String> existingSettings = settingsByModule.get(moduleKey); Map<String, String> existingSettings = settingsByModule.get(moduleKey);
Expand Down
Expand Up @@ -38,6 +38,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class); private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class);


private boolean mediumTestMode; private boolean mediumTestMode;
private boolean notAssociated;


public DefaultAnalysisMode(GlobalProperties globalProps, AnalysisProperties props) { public DefaultAnalysisMode(GlobalProperties globalProps, AnalysisProperties props) {
init(globalProps.properties(), props.properties()); init(globalProps.properties(), props.properties());
Expand All @@ -47,6 +48,10 @@ public boolean isMediumTest() {
return mediumTestMode; return mediumTestMode;
} }


public boolean isNotAssociated() {
return notAssociated;
}

private void init(Map<String, String> globalProps, Map<String, String> analysisProps) { private void init(Map<String, String> globalProps, Map<String, String> analysisProps) {
// make sure analysis is consistent with global properties // make sure analysis is consistent with global properties
boolean globalPreview = isIssues(globalProps); boolean globalPreview = isIssues(globalProps);
Expand All @@ -64,6 +69,7 @@ private void load(Map<String, String> globalProps, Map<String, String> analysisP
validate(mode); validate(mode);
issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode); issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, FakePluginInstaller.MEDIUM_TEST_ENABLED)); mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, FakePluginInstaller.MEDIUM_TEST_ENABLED));
notAssociated = issues && rootProjectKeyMissing(analysisProps);
} }


public void printMode() { public void printMode() {
Expand All @@ -77,6 +83,9 @@ public void printMode() {
if (mediumTestMode) { if (mediumTestMode) {
LOG.info("Medium test mode"); LOG.info("Medium test mode");
} }
if (notAssociated) {
LOG.info("Project is not associated with the server");
}
} }


private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) { private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) {
Expand All @@ -93,4 +102,9 @@ private static boolean isIssues(Map<String, String> props) {
return CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode); return CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode);
} }


private static boolean rootProjectKeyMissing(Map<String, String> props) {
// ProjectReactorBuilder depends on this class, so it will only create this property later
return !props.containsKey(CoreProperties.PROJECT_KEY_PROPERTY);
}

} }
Expand Up @@ -123,14 +123,22 @@ private void installPlugins() {
public void executeAnalysis(Map<String, String> analysisProperties, Object... components) { public void executeAnalysis(Map<String, String> analysisProperties, Object... components) {
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
if (isIssuesMode(props)) { if (isIssuesMode(props)) {
new ProjectSyncContainer(this, props, false).execute(); String projectKey = getProjectKeyWithBranch(props);
new ProjectSyncContainer(this, projectKey, false).execute();
} }
new ProjectScanContainer(this, props, components).execute(); new ProjectScanContainer(this, props, components).execute();
} }


public void syncProject(Map<String, String> analysisProperties, boolean force) { private static String getProjectKeyWithBranch(AnalysisProperties props) {
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); String projectKey = props.property(CoreProperties.PROJECT_KEY_PROPERTY);
new ProjectSyncContainer(this, props, force).execute(); if (projectKey != null && props.property(CoreProperties.PROJECT_BRANCH_PROPERTY) != null) {
projectKey = projectKey + ":" + props.property(CoreProperties.PROJECT_BRANCH_PROPERTY);
}
return projectKey;
}

public void syncProject(String projectKey, boolean force) {
new ProjectSyncContainer(this, projectKey, force).execute();
} }


private boolean isIssuesMode(AnalysisProperties props) { private boolean isIssuesMode(AnalysisProperties props) {
Expand Down
Expand Up @@ -19,6 +19,9 @@
*/ */
package org.sonar.batch.bootstrap; package org.sonar.batch.bootstrap;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Strings; import com.google.common.base.Strings;
Expand All @@ -27,10 +30,13 @@
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;


import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.ArrayList; import java.util.ArrayList;
Expand All @@ -55,8 +61,8 @@
*/ */
@BatchSide @BatchSide
public class ServerClient { public class ServerClient {

private static final String GET = "GET"; private static final String GET = "GET";
private static final Logger LOG = LoggerFactory.getLogger(ServerClient.class);
private GlobalProperties props; private GlobalProperties props;
private DefaultHttpDownloader.BaseHttpDownloader downloader; private DefaultHttpDownloader.BaseHttpDownloader downloader;


Expand All @@ -68,6 +74,20 @@ public ServerClient(GlobalProperties settings, EnvironmentInformation env) {
public String getURL() { public String getURL() {
return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/"); return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/");
} }

public String getServerVersion() {
InputStream is = this.getClass().getClassLoader().getResourceAsStream("sq-version.txt");
if (is == null) {
LOG.warn("Failed to get SQ version");
return null;
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
return br.readLine();
} catch (IOException e) {
LOG.warn("Failed to get SQ version", e);
return null;
}
}


public URI getURI(String pathStartingWithSlash) { public URI getURI(String pathStartingWithSlash) {
Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash); Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash);
Expand Down
Expand Up @@ -19,9 +19,6 @@
*/ */
package org.sonar.batch.bootstrapper; package org.sonar.batch.bootstrapper;


import com.google.common.collect.ImmutableMap;

import org.sonar.api.CoreProperties;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;


Expand Down Expand Up @@ -134,8 +131,7 @@ private void checkStarted() {
*/ */
public Batch syncProject(String projectKey) { public Batch syncProject(String projectKey) {
checkStarted(); checkStarted();
Map<String, String> props = ImmutableMap.of(CoreProperties.PROJECT_KEY_PROPERTY, projectKey); bootstrapContainer.syncProject(projectKey, true);
bootstrapContainer.syncProject(props, true);
return this; return this;
} }


Expand Down
Expand Up @@ -19,6 +19,8 @@
*/ */
package org.sonar.batch.cache; package org.sonar.batch.cache;


import javax.annotation.Nullable;

import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.home.cache.PersistentCache; import org.sonar.home.cache.PersistentCache;


Expand All @@ -40,7 +42,7 @@ public DefaultProjectCacheStatus(PersistentCache cache, ServerClient client) {
} }


@Override @Override
public void save(String projectKey) { public void save(@Nullable String projectKey) {
Date now = new Date(); Date now = new Date();


try { try {
Expand All @@ -55,7 +57,7 @@ public void save(String projectKey) {
} }


@Override @Override
public void delete(String projectKey) { public void delete(@Nullable String projectKey) {
try { try {
cache.put(getKey(projectKey), new byte[0]); cache.put(getKey(projectKey), new byte[0]);
} catch (IOException e) { } catch (IOException e) {
Expand All @@ -64,7 +66,7 @@ public void delete(String projectKey) {
} }


@Override @Override
public Date getSyncStatus(String projectKey) { public Date getSyncStatus(@Nullable String projectKey) {
try { try {
byte[] status = cache.get(getKey(projectKey), null); byte[] status = cache.get(getKey(projectKey), null);
if (status == null || status.length == 0) { if (status == null || status.length == 0) {
Expand All @@ -79,7 +81,11 @@ public Date getSyncStatus(String projectKey) {
} }
} }


private String getKey(String projectKey) { private String getKey(@Nullable String projectKey) {
return STATUS_PREFIX + client.getURL() + "-" + projectKey; if (projectKey != null) {
return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion() + "-" + projectKey;
} else {
return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion();
}
} }
} }

0 comments on commit 4be016e

Please sign in to comment.