aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-03-30 12:28:59 +0200
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-03-30 12:42:57 +0200
commit3fa0d737fb0177414765ca800f0271b6859437d9 (patch)
tree2ccfd4406a68f04afa3fbe056340d2a5bf08907f /server
parent06cf42d775c122816abe43a75de2b346047240d2 (diff)
parent438fd4cdc2827241186205216320623791fce9e3 (diff)
downloadsonarqube-3fa0d737fb0177414765ca800f0271b6859437d9.tar.gz
sonarqube-3fa0d737fb0177414765ca800f0271b6859437d9.zip
Merge from branch-5.1
* origin/branch-5.1: Remove log to console in unit test Fix regression on issue paging with one component Fix indexing of source lines SONAR-6340 highlight cancelled reports fix display of overlapping duplications do not show global error if the request is sent from modal window cancel analysis when the snapshot is not found - SONAR-6340 Conflicts: server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs server/sonar-web/src/main/js/source-viewer/viewer.js
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java46
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java68
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java10
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java47
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java32
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java27
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java1
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml8
-rw-r--r--server/sonar-web/src/main/coffee/analysis-reports/views/report-view.coffee1
-rw-r--r--server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs2
-rw-r--r--server/sonar-web/src/main/js/coding-rules/rule/custom-rule-creation-view.js10
-rw-r--r--server/sonar-web/src/main/js/coding-rules/rule/manual-rule-creation-view.js10
-rw-r--r--server/sonar-web/src/main/js/coding-rules/rule/profile-activation-view.js4
-rw-r--r--server/sonar-web/src/main/js/source-viewer/viewer.js12
-rw-r--r--server/sonar-web/src/main/less/pages/analysis-reports.less5
16 files changed, 234 insertions, 73 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
index 6ef7ed45e87..07108244f5c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
@@ -32,6 +32,7 @@ import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.SnapshotDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
@@ -42,11 +43,13 @@ import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
import org.sonar.server.properties.ProjectSettingsFactory;
+import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
import static org.sonar.api.utils.DateUtils.longToDate;
+import static org.sonar.core.computation.db.AnalysisReportDto.Status.*;
public class ComputationService implements ServerComponent {
@@ -73,10 +76,15 @@ public class ComputationService implements ServerComponent {
Profiler profiler = Profiler.create(LOG).startDebug(String.format(
"Analysis of project %s (report %d)", item.dto.getProjectKey(), item.dto.getId()));
- ComponentDto project = loadProject(item);
+ ComponentDto project = null;
+
try {
+ project = loadProject(item);
File reportDir = extractReportInDir(item);
BatchReportReader reader = new BatchReportReader(reportDir);
+ if (isSnapshotMissing(item, reader.readMetadata().getSnapshotId())) {
+ return;
+ }
ComputationContext context = new ComputationContext(reader, project);
context.setProjectSettings(projectSettingsFactory.newProjectSettings(project.getId()));
for (ComputationStep step : steps.orderedSteps()) {
@@ -86,10 +94,9 @@ public class ComputationService implements ServerComponent {
stepProfiler.stopDebug();
}
}
- item.dto.succeed();
-
+ item.dto.setStatus(SUCCESS);
} catch (Throwable e) {
- item.dto.fail();
+ item.dto.setStatus(FAILED);
throw Throwables.propagate(e);
} finally {
item.dto.setFinishedAt(system.now());
@@ -114,28 +121,47 @@ public class ComputationService implements ServerComponent {
}
}
- private ComponentDto loadProject(ReportQueue.Item queueItem) {
+ private ComponentDto loadProject(ReportQueue.Item item) {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.componentDao().getByKey(session, queueItem.dto.getProjectKey());
+ return dbClient.componentDao().getByKey(session, item.dto.getProjectKey());
} finally {
MyBatis.closeQuietly(session);
}
}
- private void saveActivity(AnalysisReportDto report, ComponentDto project) {
+ private boolean isSnapshotMissing(ReportQueue.Item item, long snapshotId) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ SnapshotDto snapshot = dbClient.snapshotDao().getNullableByKey(session, snapshotId);
+ if (snapshot == null) {
+ item.dto.setStatus(CANCELLED);
+ LOG.info("Processing of report #{} is canceled because it was submitted while another report of the same project was already being processed.", item.dto.getId());
+ LOG.debug("The snapshot ID #{} provided by the report #{} does not exist anymore.", snapshotId, item.dto.getId());
+ }
+ return snapshot==null;
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+
+ }
+
+ private void saveActivity(AnalysisReportDto report, @Nullable ComponentDto project) {
Activity activity = new Activity();
activity.setType(Activity.Type.ANALYSIS_REPORT);
activity.setAction("LOG_ANALYSIS_REPORT");
activity
.setData("key", String.valueOf(report.getId()))
- .setData("projectKey", project.key())
- .setData("projectName", project.name())
- .setData("projectUuid", project.uuid())
+ .setData("projectKey", report.getProjectKey())
.setData("status", String.valueOf(report.getStatus()))
.setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
.setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
.setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
+ if (project != null) {
+ activity
+ .setData("projectName", project.name())
+ .setData("projectUuid", project.uuid());
+ }
activityService.save(activity);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
index 8139db0d050..ebddc02357c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
@@ -29,6 +29,7 @@ import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.process.ProcessConstants;
+import org.sonar.server.computation.db.AnalysisReportDao;
import org.sonar.server.db.DbClient;
import javax.annotation.CheckForNull;
@@ -41,17 +42,6 @@ import java.util.List;
import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING;
public class ReportQueue implements ServerComponent {
-
- public static class Item {
- public final AnalysisReportDto dto;
- public final File zipFile;
-
- public Item(AnalysisReportDto dto, File zipFile) {
- this.dto = dto;
- this.zipFile = zipFile;
- }
- }
-
private final DbClient dbClient;
private final Settings settings;
@@ -68,18 +58,10 @@ public class ReportQueue implements ServerComponent {
try {
checkThatProjectExistsInDatabase(projectKey, session);
- // save report data on file. Directory is created if it does not exist yet.
- FileUtils.copyInputStreamToFile(reportData, file);
+ saveReportOnDisk(reportData, file);
+ AnalysisReportDto dto = saveReportMetadataInDatabase(projectKey, uuid, session);
- // add report metadata to the queue
- AnalysisReportDto dto = new AnalysisReportDto()
- .setProjectKey(projectKey)
- .setStatus(PENDING)
- .setUuid(uuid);
- dbClient.analysisReportDao().insert(session, dto);
- session.commit();
return new Item(dto, file);
-
} catch (Exception e) {
FileUtils.deleteQuietly(file);
throw new IllegalStateException("Fail to store analysis report of project " + projectKey, e);
@@ -88,6 +70,24 @@ public class ReportQueue implements ServerComponent {
}
}
+ private AnalysisReportDto saveReportMetadataInDatabase(String projectKey, String uuid, DbSession session) {
+ AnalysisReportDto dto = new AnalysisReportDto()
+ .setProjectKey(projectKey)
+ .setStatus(PENDING)
+ .setUuid(uuid);
+ dao().insert(session, dto);
+ session.commit();
+ return dto;
+ }
+
+ private AnalysisReportDao dao() {
+ return dbClient.analysisReportDao();
+ }
+
+ private void saveReportOnDisk(InputStream reportData, File file) throws IOException {
+ FileUtils.copyInputStreamToFile(reportData, file);
+ }
+
private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) {
dbClient.componentDao().getByKey(session, projectKey);
}
@@ -96,7 +96,7 @@ public class ReportQueue implements ServerComponent {
DbSession session = dbClient.openSession(false);
try {
FileUtils.deleteQuietly(item.zipFile);
- dbClient.analysisReportDao().delete(session, item.dto.getId());
+ dao().delete(session, item.dto.getId());
session.commit();
} finally {
MyBatis.closeQuietly(session);
@@ -107,14 +107,14 @@ public class ReportQueue implements ServerComponent {
public Item pop() {
DbSession session = dbClient.openSession(false);
try {
- AnalysisReportDto dto = dbClient.analysisReportDao().pop(session);
+ AnalysisReportDto dto = dao().pop(session);
if (dto != null) {
File file = reportFileForUuid(dto.getUuid());
if (file.exists()) {
return new Item(dto, file);
}
Loggers.get(getClass()).error("Analysis report not found: " + file.getAbsolutePath());
- dbClient.analysisReportDao().delete(session, dto.getId());
+ dao().delete(session, dto.getId());
session.commit();
}
return null;
@@ -123,10 +123,10 @@ public class ReportQueue implements ServerComponent {
}
}
- public List<AnalysisReportDto> findByProjectKey(String projectKey) {
+ public List<AnalysisReportDto> selectByProjectKey(String projectKey) {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.analysisReportDao().selectByProjectKey(session, projectKey);
+ return dao().selectByProjectKey(session, projectKey);
} finally {
MyBatis.closeQuietly(session);
}
@@ -145,7 +145,7 @@ public class ReportQueue implements ServerComponent {
DbSession session = dbClient.openSession(false);
try {
- dbClient.analysisReportDao().truncate(session);
+ dao().truncate(session);
session.commit();
} finally {
MyBatis.closeQuietly(session);
@@ -155,7 +155,7 @@ public class ReportQueue implements ServerComponent {
public void resetToPendingStatus() {
DbSession session = dbClient.openSession(false);
try {
- dbClient.analysisReportDao().resetAllToPendingStatus(session);
+ dao().resetAllToPendingStatus(session);
session.commit();
} finally {
MyBatis.closeQuietly(session);
@@ -168,7 +168,7 @@ public class ReportQueue implements ServerComponent {
public List<AnalysisReportDto> all() {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.analysisReportDao().selectAll(session);
+ return dao().selectAll(session);
} finally {
MyBatis.closeQuietly(session);
}
@@ -185,4 +185,14 @@ public class ReportQueue implements ServerComponent {
private File reportFileForUuid(String uuid) {
return new File(reportsDir(), String.format("%s.zip", uuid));
}
+
+ public static class Item {
+ public final AnalysisReportDto dto;
+ public final File zipFile;
+
+ public Item(AnalysisReportDto dto, File zipFile) {
+ this.dto = dto;
+ this.zipFile = zipFile;
+ }
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
index a43ba7a4fcd..c10ad36fe33 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java
@@ -64,6 +64,7 @@ public class BulkIndexer implements Startable {
private final EsClient client;
private final String indexName;
private boolean large = false;
+ private long flushByteSize = FLUSH_BYTE_SIZE;
private boolean disableRefresh = false;
private BulkRequestBuilder bulkRequest = null;
private Map<String, Object> largeInitialSettings = null;
@@ -92,6 +93,11 @@ public class BulkIndexer implements Startable {
return this;
}
+ public BulkIndexer setFlushByteSize(long flushByteSize) {
+ this.flushByteSize = flushByteSize;
+ return this;
+ }
+
/**
* By default refresh of index is executed in method {@link #stop()}. Set to true
* to disable refresh.
@@ -130,7 +136,7 @@ public class BulkIndexer implements Startable {
public void add(ActionRequest request) {
bulkRequest.request().add(request);
- if (bulkRequest.request().estimatedSizeInBytes() >= FLUSH_BYTE_SIZE) {
+ if (bulkRequest.request().estimatedSizeInBytes() >= flushByteSize) {
executeBulk();
}
}
@@ -139,6 +145,7 @@ public class BulkIndexer implements Startable {
searchRequest
.setScroll(TimeValue.timeValueMinutes(5))
.setSearchType(SearchType.SCAN)
+ .setSize(100)
// load only doc ids, not _source fields
.setFetchSource(false);
@@ -147,9 +154,18 @@ public class BulkIndexer implements Startable {
// Same semaphore can't be reused because of potential deadlock (requires to acquire
// two locks)
SearchResponse searchResponse = searchRequest.get();
- searchResponse = client.prepareSearchScroll(searchResponse.getScrollId()).get();
- for (SearchHit hit : searchResponse.getHits()) {
- add(client.prepareDelete(hit.index(), hit.type(), hit.getId()).request());
+
+ while (true) {
+ searchResponse = client.prepareSearchScroll(searchResponse.getScrollId())
+ .setScroll(TimeValue.timeValueMinutes(5))
+ .get();
+ SearchHit[] hits = searchResponse.getHits().getHits();
+ for (SearchHit hit : hits) {
+ add(client.prepareDelete(hit.index(), hit.type(), hit.getId()).request());
+ }
+ if (hits.length == 0) {
+ break;
+ }
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
index 90be2256aba..e9045bf88e4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
@@ -269,6 +269,9 @@ public class SearchAction implements BaseIssuesWsAction {
public final void handle(Request request, Response response) throws Exception {
SearchOptions options = new SearchOptions();
options.setPage(request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE));
+ if (shouldIgnorePaging(request)) {
+ options.disableLimit();
+ }
options.addFacets(request.paramAsStrings(WebService.Param.FACETS));
IssueQuery query = issueQueryService.createFromRequest(request);
@@ -285,6 +288,13 @@ public class SearchAction implements BaseIssuesWsAction {
json.endObject().close();
}
+ private boolean shouldIgnorePaging(Request request) {
+ List<String> componentUuids = request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS);
+ // Paging can be ignored only when querying issues for a single component (e.g in component viewer)
+ return componentUuids != null && componentUuids.size() == 1
+ && BooleanUtils.isTrue(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING));
+ }
+
private SearchResult<IssueDoc> execute(IssueQuery query, SearchOptions options) {
Collection<String> components = query.componentUuids();
if (components != null && components.size() == 1 && BooleanUtils.isTrue(query.ignorePaging())) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
index b2e8f78452a..5beec075d1b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
@@ -32,13 +32,15 @@ import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.internal.JUnitTempFolder;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.db.AnalysisReportDto.Status;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.activity.Activity;
import org.sonar.server.activity.ActivityService;
import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
@@ -55,15 +57,13 @@ import static org.mockito.Mockito.*;
public class ComputationServiceTest {
+ private static final long ANY_SNAPSHOT_ID = 54987654231L;
@ClassRule
public static DbTester dbTester = new DbTester();
-
@Rule
public JUnitTempFolder tempFolder = new JUnitTempFolder();
-
@Rule
public LogTester logTester = new LogTester();
-
ComputationStep projectStep1 = mockStep(Qualifiers.PROJECT);
ComputationStep projectStep2 = mockStep(Qualifiers.PROJECT);
ComputationStep viewStep = mockStep(Qualifiers.VIEW);
@@ -75,7 +75,7 @@ public class ComputationServiceTest {
@Before
public void setUp() throws Exception {
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
+ DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao(), new SnapshotDao(system));
sut = new ComputationService(dbClient, steps, activityService, settingsFactory, tempFolder, system);
// db contains project with key "P1"
@@ -88,13 +88,13 @@ public class ComputationServiceTest {
// view step is not supposed to be executed
when(steps.orderedSteps()).thenReturn(Arrays.asList(projectStep1, projectStep2, viewStep));
- AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ AnalysisReportDto dto = newDefaultReport();
File zip = generateZip();
sut.process(new ReportQueue.Item(dto, zip));
// report is integrated -> status is set to SUCCESS
- assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.SUCCESS);
+ assertThat(dto.getStatus()).isEqualTo(Status.SUCCESS);
assertThat(dto.getFinishedAt()).isNotNull();
// one info log at the end
@@ -108,11 +108,15 @@ public class ComputationServiceTest {
verify(activityService).save(any(Activity.class));
}
+ private AnalysisReportDto newDefaultReport() {
+ return AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(Status.PENDING);
+ }
+
@Test
public void debug_logs() throws Exception {
logTester.setLevel(LoggerLevel.DEBUG);
- AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ AnalysisReportDto dto = newDefaultReport();
File zip = generateZip();
sut.process(new ReportQueue.Item(dto, zip));
@@ -121,7 +125,7 @@ public class ComputationServiceTest {
@Test
public void fail_if_corrupted_zip() throws Exception {
- AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ AnalysisReportDto dto = newDefaultReport();
File zip = tempFolder.newFile();
FileUtils.write(zip, "not a file");
@@ -130,7 +134,7 @@ public class ComputationServiceTest {
fail();
} catch (IllegalStateException e) {
assertThat(e.getMessage()).startsWith("Fail to unzip " + zip.getAbsolutePath() + " into ");
- assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.FAILED);
+ assertThat(dto.getStatus()).isEqualTo(Status.FAILED);
assertThat(dto.getFinishedAt()).isNotNull();
}
}
@@ -140,7 +144,7 @@ public class ComputationServiceTest {
when(steps.orderedSteps()).thenReturn(Arrays.asList(projectStep1));
doThrow(new IllegalStateException("pb")).when(projectStep1).execute(any(ComputationContext.class));
- AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1");
+ AnalysisReportDto dto = newDefaultReport();
File zip = generateZip();
try {
@@ -148,11 +152,25 @@ public class ComputationServiceTest {
fail();
} catch (IllegalStateException e) {
assertThat(e.getMessage()).isEqualTo("pb");
- assertThat(dto.getStatus()).isEqualTo(AnalysisReportDto.Status.FAILED);
+ assertThat(dto.getStatus()).isEqualTo(Status.FAILED);
assertThat(dto.getFinishedAt()).isNotNull();
}
}
+ @Test
+ public void analysis_cancelled_when_snapshot_not_found() throws Exception {
+ AnalysisReportDto report = newDefaultReport();
+ File zip = generateZip(ANY_SNAPSHOT_ID);
+ logTester.setLevel(LoggerLevel.DEBUG);
+
+ sut.process(new ReportQueue.Item(report, zip));
+
+ assertThat(report.getStatus()).isEqualTo(Status.CANCELLED);
+ assertThat(logTester.logs()).contains(
+ String.format("Processing of report #%s is canceled because it was submitted while another report of the same project was already being processed.", report.getId()));
+ assertThat(logTester.logs()).contains(String.format("The snapshot ID #%s provided by the report #%s does not exist anymore.", ANY_SNAPSHOT_ID, report.getId()));
+ }
+
private ComputationStep mockStep(String... qualifiers) {
ComputationStep step = mock(ComputationStep.class);
when(step.supportedProjectQualifiers()).thenReturn(qualifiers);
@@ -161,12 +179,17 @@ public class ComputationServiceTest {
}
private File generateZip() throws IOException {
+ return generateZip(110L);
+ }
+
+ private File generateZip(long snapshotId) throws IOException {
File dir = tempFolder.newDir();
BatchReportWriter writer = new BatchReportWriter(dir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
+ .setSnapshotId(snapshotId)
.build());
File zip = tempFolder.newFile();
ZipUtils.zipDir(dir, zip);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
index 6db7d0c9eb8..54d29d63e68 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
@@ -40,7 +40,6 @@ import org.sonar.server.db.DbClient;
import org.sonar.test.DbTests;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@@ -56,7 +55,7 @@ public class ReportQueueTest {
static final long NOW = 1_500_000_000_000L;
@Rule
- public DbTester dbTester = new DbTester();
+ public DbTester db = new DbTester();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -72,7 +71,7 @@ public class ReportQueueTest {
settings.setProperty(ProcessConstants.PATH_DATA, dataDir.getAbsolutePath());
when(system.now()).thenReturn(NOW);
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao(), new AnalysisReportDao(system));
+ DbClient dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new AnalysisReportDao(system));
sut = new ReportQueue(dbClient, settings);
try (DbSession session = dbClient.openSession(false)) {
@@ -84,7 +83,7 @@ public class ReportQueueTest {
}
@Test
- public void add_report_to_queue() throws IOException {
+ public void add_report_to_queue() throws Exception {
// must:
// 1. insert metadata in db
// 2. copy report content to directory /data/analysis
@@ -95,7 +94,7 @@ public class ReportQueueTest {
assertThat(item.dto.getUuid()).isNotEmpty();
assertThat(item.dto.getId()).isGreaterThan(0L);
- List<AnalysisReportDto> reports = sut.findByProjectKey("P1");
+ List<AnalysisReportDto> reports = sut.selectByProjectKey("P1");
assertThat(reports).hasSize(1);
AnalysisReportDto report = reports.get(0);
@@ -115,8 +114,8 @@ public class ReportQueueTest {
@Test
public void find_by_project_key() throws Exception {
sut.add("P1", generateData());
- assertThat(sut.findByProjectKey("P1")).hasSize(1).extracting("projectKey").containsExactly("P1");
- assertThat(sut.findByProjectKey("P2")).isEmpty();
+ assertThat(sut.selectByProjectKey("P1")).hasSize(1).extracting("projectKey").containsExactly("P1");
+ assertThat(sut.selectByProjectKey("P2")).isEmpty();
}
@Test
@@ -147,10 +146,10 @@ public class ReportQueueTest {
@Test
public void remove() {
ReportQueue.Item item = sut.add("P1", generateData());
- assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(1);
+ assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(1);
sut.remove(item);
- assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
assertThat(item.zipFile).doesNotExist();
}
@@ -164,7 +163,7 @@ public class ReportQueueTest {
assertThat(sut.pop()).isNull();
// table sanitized
- assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
}
@Test
@@ -175,11 +174,22 @@ public class ReportQueueTest {
sut.clear();
- assertThat(dbTester.countRowsOfTable("analysis_reports")).isEqualTo(0);
+ assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
assertThat(analysisDir()).doesNotExist();
}
@Test
+ public void clear_do_not_fail_when_directory_do_not_exist() throws Exception {
+ sut.clear();
+ sut.clear();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void add_on_non_existent_project() throws Exception {
+ sut.add("UNKNOWN_PROJECT_KEY", generateData());
+ }
+
+ @Test
public void reset_to_pending_status() throws Exception {
// 2 pending
sut.add("P1", generateData());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
index 6cb28e3db7e..93692d16570 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/BulkIndexerTest.java
@@ -22,10 +22,15 @@ package org.sonar.server.es;
import com.google.common.collect.ImmutableMap;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Rule;
import org.junit.Test;
+import java.util.Map;
+
import static org.assertj.core.api.Assertions.assertThat;
public class BulkIndexerTest {
@@ -65,6 +70,7 @@ public class BulkIndexerTest {
assertThat(replicas()).isEqualTo(1);
BulkIndexer indexer = new BulkIndexer(esTester.client(), FakeIndexDefinition.INDEX)
+ .setFlushByteSize(500)
.setLarge(true);
indexer.start();
@@ -83,6 +89,27 @@ public class BulkIndexerTest {
}
@Test
+ public void bulk_delete() throws Exception {
+ int max = 500;
+ int removeFrom = 200;
+ Map[] docs = new Map[max];
+ for (int i = 0; i < max; i++) {
+ docs[i] = ImmutableMap.of(FakeIndexDefinition.INT_FIELD, i);
+ }
+ esTester.putDocuments(FakeIndexDefinition.INDEX, FakeIndexDefinition.TYPE, docs);
+ assertThat(count()).isEqualTo(max);
+
+ SearchRequestBuilder req = esTester.client().prepareSearch(FakeIndexDefinition.INDEX)
+ .setTypes(FakeIndexDefinition.TYPE)
+ .setQuery(QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(),
+ FilterBuilders.rangeFilter(FakeIndexDefinition.INT_FIELD).gte(removeFrom)));
+ BulkIndexer.delete(esTester.client(), FakeIndexDefinition.INDEX, req);
+
+ assertThat(count()).isEqualTo(removeFrom);
+ }
+
+ @Test
public void disable_refresh() throws Exception {
BulkIndexer indexer = new BulkIndexer(esTester.client(), FakeIndexDefinition.INDEX)
.setDisableRefresh(true);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java
index 6d6759b1575..6e7ee3749d3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java
@@ -528,7 +528,6 @@ public class SearchActionComponentsMediumTest {
Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, technicalProject.uuid())
.execute();
- System.out.println(result.outputAsString());
result
.assertJson(this.getClass(), "search_by_developer.json");
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
index 66bd86524aa..bdf91f3f145 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/ComputationServiceTest/shared.xml
@@ -1,3 +1,11 @@
<dataset>
<projects id="10" kee="P1" qualifier="TRK"/>
+ <snapshots
+ id="110" project_id="10" parent_snapshot_id="[null]" root_project_id="10" root_snapshot_id="[null]"
+ purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+ period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+ period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="false" depth="0"/>
</dataset>
diff --git a/server/sonar-web/src/main/coffee/analysis-reports/views/report-view.coffee b/server/sonar-web/src/main/coffee/analysis-reports/views/report-view.coffee
index 66411deeea8..81b6f8bd034 100644
--- a/server/sonar-web/src/main/coffee/analysis-reports/views/report-view.coffee
+++ b/server/sonar-web/src/main/coffee/analysis-reports/views/report-view.coffee
@@ -32,6 +32,7 @@ define [
@$el.addClass 'analysis-reports-report-pending' if status is 'PENDING'
@$el.addClass 'analysis-reports-report-working' if status is 'WORKING'
@$el.addClass 'analysis-reports-report-done' if status is 'SUCCESS'
+ @$el.addClass 'analysis-reports-report-cancelled' if status is 'CANCELLED'
@$el.addClass 'analysis-reports-report-failed' if status is 'FAIL'
diff --git a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
index 4a596a1959d..433825e60cf 100644
--- a/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
+++ b/server/sonar-web/src/main/hbs/source-viewer/source-viewer-duplication-popup.hbs
@@ -21,7 +21,7 @@
{{#notEq file.key ../component.key}}
<div class="component-name-path">
- <a data-uuid="{{file.uuid}}" title="{{file.name}}">
+ <a class="link-action" data-uuid="{{file.uuid}}" title="{{file.name}}">
<span>{{collapsedDirFromPath file.name}}</span><span
class="component-name-file">{{fileFromPath file.name}}</span>
</a>
diff --git a/server/sonar-web/src/main/js/coding-rules/rule/custom-rule-creation-view.js b/server/sonar-web/src/main/js/coding-rules/rule/custom-rule-creation-view.js
index 1443c801805..3ff81d43723 100644
--- a/server/sonar-web/src/main/js/coding-rules/rule/custom-rule-creation-view.js
+++ b/server/sonar-web/src/main/js/coding-rules/rule/custom-rule-creation-view.js
@@ -154,7 +154,15 @@ define([
this.$('.alert').addClass('hidden');
var that = this,
url = baseUrl + '/api/rules/' + action;
- return $.post(url, options).done(function () {
+ return $.ajax({
+ url: url,
+ type: 'POST',
+ data: options,
+ statusCode: {
+ // do not show global error
+ 400: null
+ }
+ }).done(function () {
if (that.options.templateRule) {
that.options.app.controller.showDetails(that.options.templateRule);
} else {
diff --git a/server/sonar-web/src/main/js/coding-rules/rule/manual-rule-creation-view.js b/server/sonar-web/src/main/js/coding-rules/rule/manual-rule-creation-view.js
index d9f2e20c2a3..6fd9ce49c3f 100644
--- a/server/sonar-web/src/main/js/coding-rules/rule/manual-rule-creation-view.js
+++ b/server/sonar-web/src/main/js/coding-rules/rule/manual-rule-creation-view.js
@@ -102,7 +102,15 @@ define([
sendRequest: function (action, options) {
var that = this,
url = baseUrl + '/api/rules/' + action;
- return $.post(url, options).done(function (r) {
+ return $.ajax({
+ url: url,
+ type: 'POST',
+ data: options,
+ statusCode: {
+ // do not show global error
+ 400: null
+ }
+ }).done(function (r) {
if (typeof r === 'string') {
r = JSON.parse(r);
}
diff --git a/server/sonar-web/src/main/js/coding-rules/rule/profile-activation-view.js b/server/sonar-web/src/main/js/coding-rules/rule/profile-activation-view.js
index 18362015704..2e2e0f9be56 100644
--- a/server/sonar-web/src/main/js/coding-rules/rule/profile-activation-view.js
+++ b/server/sonar-web/src/main/js/coding-rules/rule/profile-activation-view.js
@@ -103,6 +103,10 @@ define([
rule_key: ruleKey,
severity: severity,
params: paramsHash
+ },
+ statusCode: {
+ // do not show global error
+ 400: null
}
}).done(function () {
that.trigger('profileActivated', severity, params);
diff --git a/server/sonar-web/src/main/js/source-viewer/viewer.js b/server/sonar-web/src/main/js/source-viewer/viewer.js
index 72f197f7008..66600022fa2 100644
--- a/server/sonar-web/src/main/js/source-viewer/viewer.js
+++ b/server/sonar-web/src/main/js/source-viewer/viewer.js
@@ -434,10 +434,16 @@ define([
blocks = this.model.get('duplications')[index - 1].blocks,
inRemovedComponent = _.some(blocks, function (b) {
return b._ref == null;
- });
+ }),
+ foundOne = false;
blocks = _.filter(blocks, function (b) {
- var outOfBounds = b.from > line || b.from + b.size < line;
- return (b._ref != null) && ((b._ref !== '1') || (b._ref === '1' && outOfBounds));
+ var outOfBounds = b.from > line || b.from + b.size < line,
+ currentFile = b._ref === '1',
+ isOk = (b._ref != null) && (!currentFile || (currentFile && (outOfBounds || foundOne)));
+ if (b._ref === '1' && !outOfBounds) {
+ foundOne = true;
+ }
+ return isOk;
});
var popup = new DuplicationPopupView({
triggerEl: $(e.currentTarget),
diff --git a/server/sonar-web/src/main/less/pages/analysis-reports.less b/server/sonar-web/src/main/less/pages/analysis-reports.less
index df4abf70d11..b995f9412dd 100644
--- a/server/sonar-web/src/main/less/pages/analysis-reports.less
+++ b/server/sonar-web/src/main/less/pages/analysis-reports.less
@@ -27,6 +27,7 @@
@pendingColor: #fdfce2;
@workingColor: #ecf9fc;
@doneColor: #ecfced;
+@cancelledColor: #fcecec;
@failedColor: #fcecec;
@@ -59,6 +60,10 @@
background-color: @doneColor !important;
}
+.analysis-reports-report-cancelled {
+ background-color: @cancelledColor !important;
+}
+
.analysis-reports-report-failed {
background-color: @failedColor !important;