diff options
author | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2015-03-30 12:28:59 +0200 |
---|---|---|
committer | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2015-03-30 12:42:57 +0200 |
commit | 3fa0d737fb0177414765ca800f0271b6859437d9 (patch) | |
tree | 2ccfd4406a68f04afa3fbe056340d2a5bf08907f /server | |
parent | 06cf42d775c122816abe43a75de2b346047240d2 (diff) | |
parent | 438fd4cdc2827241186205216320623791fce9e3 (diff) | |
download | sonarqube-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')
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; |