diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-10-09 18:14:26 +0200 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-10-14 16:39:35 +0200 |
commit | 0aca00fedfab427f0e0dc0234354f9b1f3a31a9c (patch) | |
tree | 78254e0c22204467a6526e0aed5ad6e86fdc15a3 | |
parent | 0ef3c7ba4091421f65977c77819c38bce79fdab8 (diff) | |
download | sonarqube-0aca00fedfab427f0e0dc0234354f9b1f3a31a9c.tar.gz sonarqube-0aca00fedfab427f0e0dc0234354f9b1f3a31a9c.zip |
SONAR-5698 SRP for ComputationService and Exception management enhancement
13 files changed, 338 insertions, 224 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java index e600326edb6..5964d0ac880 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java @@ -24,6 +24,7 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; +import org.sonar.server.computation.AnalysisReportQueue; import org.sonar.server.computation.AnalysisReportTask; import org.sonar.server.computation.AnalysisReportTaskLauncher; import org.sonar.server.computation.ComputationService; @@ -34,10 +35,12 @@ public class UploadReportAction implements RequestHandler { static final String PARAM_PROJECT = "project"; + private final AnalysisReportQueue queue; private final ComputationService computationService; private final AnalysisReportTaskLauncher analysisTaskLauncher; - public UploadReportAction(ComputationService computationService, AnalysisReportTaskLauncher analysisTaskLauncher) { + public UploadReportAction(AnalysisReportQueue queue, ComputationService computationService, AnalysisReportTaskLauncher analysisTaskLauncher) { + this.queue = queue; this.computationService = computationService; this.analysisTaskLauncher = analysisTaskLauncher; } @@ -61,10 +64,10 @@ public class UploadReportAction implements RequestHandler { public void handle(Request request, Response response) throws Exception { String projectKey = request.mandatoryParam(PARAM_PROJECT); - computationService.addAnalysisReport(projectKey); + queue.add(projectKey); // TODO remove synchronization as soon as it won't break ITs ! - (new AnalysisReportTask(computationService)).run(); + (new AnalysisReportTask(queue, computationService)).run(); analysisTaskLauncher.startAnalysisTaskNow(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java new file mode 100644 index 00000000000..d01e3cc5a74 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java @@ -0,0 +1,123 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerComponent; +import org.sonar.core.computation.db.AnalysisReportDto; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.computation.db.AnalysisReportDao; +import org.sonar.server.db.DbClient; +import org.sonar.server.user.UserSession; + +import javax.annotation.CheckForNull; + +import java.util.List; + +import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING; + +public class AnalysisReportQueue implements ServerComponent { + private static final Logger LOG = LoggerFactory.getLogger(ComputationService.class); + + private final DbClient dbClient; + private final AnalysisReportDao dao; + + public AnalysisReportQueue(DbClient dbClient) { + this.dbClient = dbClient; + this.dao = dbClient.analysisReportDao(); + } + + public AnalysisReportDto add(String projectKey) { + UserSession.get().checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION); + + AnalysisReportDto report = newPendingAnalysisReport(projectKey); + + DbSession session = dbClient.openSession(false); + try { + checkThatProjectExistsInDatabase(projectKey, session); + return insertInDatabase(report, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + private AnalysisReportDto insertInDatabase(AnalysisReportDto reportTemplate, DbSession session) { + AnalysisReportDto report = dao.insert(session, reportTemplate); + session.commit(); + + return report; + } + + private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) { + dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); + } + + private AnalysisReportDto newPendingAnalysisReport(String projectKey) { + return new AnalysisReportDto() + .setProjectKey(projectKey) + .setStatus(PENDING); + } + + public void remove(AnalysisReportDto report) { + DbSession session = dbClient.openSession(false); + + try { + dao.delete(session, report); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + /** + * @return a booked analysis report if one is available, null otherwise + */ + @CheckForNull + public synchronized AnalysisReportDto bookNextAvailable() { + DbSession session = dbClient.openSession(false); + try { + AnalysisReportDto nextAvailableReport = dao.getNextAvailableReport(session); + if (nextAvailableReport == null) { + return null; + } + + AnalysisReportDto report = dao.tryToBookReportAnalysis(session, nextAvailableReport); + session.commit(); + + return report; + } finally { + MyBatis.closeQuietly(session); + } + } + + public List<AnalysisReportDto> findByProjectKey(String projectKey) { + DbSession session = dbClient.openSession(false); + try { + return dao.findByProjectKey(session, projectKey); + } finally { + MyBatis.closeQuietly(session); + } + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTask.java index 64349a575bd..56a64c03783 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTask.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTask.java @@ -20,21 +20,31 @@ package org.sonar.server.computation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.core.computation.db.AnalysisReportDto; public class AnalysisReportTask implements Runnable { + private static final Logger LOG = LoggerFactory.getLogger(AnalysisReportTask.class); + private final AnalysisReportQueue queue; private final ComputationService service; - public AnalysisReportTask(ComputationService service) { + public AnalysisReportTask(AnalysisReportQueue queue, ComputationService service) { + this.queue = queue; this.service = service; } @Override public void run() { - AnalysisReportDto report = service.findAndBookNextAvailableAnalysisReport(); + AnalysisReportDto report = queue.bookNextAvailable(); if (report != null) { - service.analyzeReport(report); + try { + service.analyzeReport(report); + queue.remove(report); + } catch (Exception exception) { + LOG.error(String.format("Analysis of report %s failed", report), exception); + } } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTaskLauncher.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTaskLauncher.java index 3283b159b52..3ca8a8b90fc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTaskLauncher.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTaskLauncher.java @@ -34,14 +34,16 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent { private final Logger LOG = LoggerFactory.getLogger(AnalysisReportTaskLauncher.class); private final ComputationService service; + private final AnalysisReportQueue queue; private final ScheduledExecutorService executorService; private final long delayBetweenTasks; private final long delayForFirstStart; private final TimeUnit timeUnit; - public AnalysisReportTaskLauncher(ComputationService service) { + public AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue) { this.service = service; + this.queue = queue; this.executorService = Executors.newSingleThreadScheduledExecutor(); this.delayBetweenTasks = 10; @@ -50,7 +52,8 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent { } @VisibleForTesting - AnalysisReportTaskLauncher(ComputationService service, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) { + AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) { + this.queue = queue; this.executorService = Executors.newSingleThreadScheduledExecutor(); this.delayBetweenTasks = delayBetweenTasks; @@ -61,7 +64,7 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent { @Override public void start() { - executorService.scheduleAtFixedRate(new AnalysisReportTask(service), delayForFirstStart, delayBetweenTasks, timeUnit); + executorService.scheduleAtFixedRate(new AnalysisReportTask(queue, service), delayForFirstStart, delayBetweenTasks, timeUnit); LOG.info("AnalysisReportTaskLauncher started"); } @@ -72,6 +75,6 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent { } public void startAnalysisTaskNow() { - executorService.execute(new AnalysisReportTask(service)); + executorService.execute(new AnalysisReportTask(queue, service)); } } 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 46d2199808d..0bc77eb5729 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 @@ -25,7 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.ServerComponent; import org.sonar.core.computation.db.AnalysisReportDto; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.server.computation.db.AnalysisReportDao; @@ -34,13 +33,6 @@ import org.sonar.server.issue.index.IssueAuthorizationIndex; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.search.IndexClient; -import org.sonar.server.user.UserSession; - -import javax.annotation.CheckForNull; - -import java.util.List; - -import static org.sonar.core.computation.db.AnalysisReportDto.Status.PENDING; /** * since 5.0 @@ -60,63 +52,6 @@ public class ComputationService implements ServerComponent { this.permissionService = permissionService; } - public void addAnalysisReport(String projectKey) { - UserSession.get().checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION); - - AnalysisReportDto report = newPendingAnalysisReport(projectKey); - - DbSession session = dbClient.openSession(false); - try { - checkThatProjectExistsInDatabase(projectKey, session); - insertReportInDatabase(report, session); - } finally { - MyBatis.closeQuietly(session); - } - } - - private void insertReportInDatabase(AnalysisReportDto report, DbSession session) { - dao.insert(session, report); - session.commit(); - } - - private void checkThatProjectExistsInDatabase(String projectKey, DbSession session) { - dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); - } - - private AnalysisReportDto newPendingAnalysisReport(String projectKey) { - return new AnalysisReportDto().setProjectKey(projectKey).setStatus(PENDING); - } - - public List<AnalysisReportDto> findByProjectKey(String projectKey) { - DbSession session = dbClient.openSession(false); - try { - return dao.findByProjectKey(session, projectKey); - } finally { - MyBatis.closeQuietly(session); - } - } - - /** - * @return a booked analysis report if one is available, null otherwise - */ - @CheckForNull - public synchronized AnalysisReportDto findAndBookNextAvailableAnalysisReport() { - DbSession session = dbClient.openSession(false); - try { - AnalysisReportDto nextAvailableReport = dao.getNextAvailableReport(session); - if (nextAvailableReport == null) { - return null; - } - - AnalysisReportDto report = dao.bookAnalysisReport(session, nextAvailableReport); - session.commit(); - - return report; - } finally { - MyBatis.closeQuietly(session); - } - } - public void analyzeReport(AnalysisReportDto report) { // Synchronization of lot of data can only be done with a batch session for the moment DbSession session = dbClient.openSession(true); @@ -125,25 +60,13 @@ public class ComputationService implements ServerComponent { try { synchronizeProjectPermissionsIfNotFound(session, projectKey); indexProjectIssues(session, projectKey); - } catch (Exception exception) { - LOG.error(String.format("Error while analyzing %s'", report), exception); } finally { - removeSilentlyReportFromQueue(session, report); MyBatis.closeQuietly(session); } LOG.info(String.format("Analysis of %s successfully finished.", report)); } - private void removeSilentlyReportFromQueue(DbSession session, AnalysisReportDto report) { - try { - dao.delete(session, report); - session.commit(); - } catch (Exception exception) { - LOG.error(String.format("Error while the report analysis, deleting %s", report), exception); - } - } - private void indexProjectIssues(DbSession session, String projectKey) { dbClient.issueDao().synchronizeAfter(session, index.get(IssueIndex.class).getLastSynchronization(), diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 381586b49fd..0cb3aa5d42f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -85,6 +85,7 @@ import org.sonar.server.component.DefaultRubyComponentService; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; import org.sonar.server.component.ws.*; +import org.sonar.server.computation.AnalysisReportQueue; import org.sonar.server.computation.AnalysisReportTaskCleaner; import org.sonar.server.computation.AnalysisReportTaskLauncher; import org.sonar.server.computation.ComputationService; @@ -588,6 +589,7 @@ class ServerComponents { // Compute engine pico.addSingleton(ComputationService.class); + pico.add(AnalysisReportQueue.class); pico.addSingleton(AnalysisReportTaskLauncher.class); for (Object components : level4AddedComponents) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java index 709b1f762ca..456393159ec 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java @@ -30,6 +30,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.resources.Languages; import org.sonar.core.properties.PropertiesDao; +import org.sonar.server.computation.AnalysisReportQueue; import org.sonar.server.computation.AnalysisReportTaskLauncher; import org.sonar.server.computation.ComputationService; import org.sonar.server.db.DbClient; @@ -62,10 +63,10 @@ public class BatchWsTest { @Before public void before() throws IOException { tester = new WsTester(new BatchWs(batchIndex, - new GlobalReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class)), - new ProjectReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class), mock(QProfileFactory.class), mock(QProfileLoader.class), mock(RuleService.class), - mock(Languages.class)), - new UploadReportAction(mock(ComputationService.class), mock(AnalysisReportTaskLauncher.class)))); + new GlobalReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class)), + new ProjectReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class), mock(QProfileFactory.class), mock(QProfileLoader.class), mock(RuleService.class), + mock(Languages.class)), + new UploadReportAction(mock(AnalysisReportQueue.class), mock(ComputationService.class), mock(AnalysisReportTaskLauncher.class)))); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionTest.java index c306119bcfe..05171c67759 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionTest.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; +import org.sonar.server.computation.AnalysisReportQueue; import org.sonar.server.computation.AnalysisReportTaskLauncher; import org.sonar.server.computation.ComputationService; @@ -37,13 +38,15 @@ public class UploadReportActionTest { private ComputationService computationService; private AnalysisReportTaskLauncher analysisTaskLauncher; + private AnalysisReportQueue queue; @Before public void before() { computationService = mock(ComputationService.class); analysisTaskLauncher = mock(AnalysisReportTaskLauncher.class); + queue = mock(AnalysisReportQueue.class); - sut = new UploadReportAction(computationService, analysisTaskLauncher); + sut = new UploadReportAction(queue, computationService, analysisTaskLauncher); } @Test @@ -54,7 +57,7 @@ public class UploadReportActionTest { sut.handle(request, response); - verify(computationService).addAnalysisReport(DEFAULT_PROJECT_KEY); + verify(queue).add(DEFAULT_PROJECT_KEY); verify(analysisTaskLauncher).startAnalysisTaskNow(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java new file mode 100644 index 00000000000..b362b765237 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java @@ -0,0 +1,145 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.security.DefaultGroups; +import org.sonar.api.web.UserRole; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.computation.db.AnalysisReportDto; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.permission.PermissionFacade; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.user.UserDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.tester.ServerTester; +import org.sonar.server.user.MockUserSession; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; +import static org.sonar.core.computation.db.AnalysisReportDto.Status.WORKING; + +public class AnalysisReportQueueMediumTest { + private static final String DEFAULT_PROJECT_KEY = "123456789-987654321"; + + @ClassRule + public static ServerTester tester = new ServerTester(); + + private AnalysisReportQueue sut; + + private DbClient db; + private DbSession session; + private MockUserSession userSession; + + @Before + public void setUp() throws Exception { + tester.clearDbAndIndexes(); + db = tester.get(DbClient.class); + session = db.openSession(false); + + sut = tester.get(AnalysisReportQueue.class); + + UserDto connectedUser = new UserDto().setLogin("gandalf").setName("Gandalf"); + db.userDao().insert(session, connectedUser); + + userSession = MockUserSession.set() + .setLogin(connectedUser.getLogin()) + .setUserId(connectedUser.getId().intValue()) + .setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + + session.commit(); + } + + @After + public void after() { + MyBatis.closeQuietly(session); + } + + @Test + public void create_analysis_report_and_retrieve_it() { + insertPermissionsForProject(DEFAULT_PROJECT_KEY); + sut.add(DEFAULT_PROJECT_KEY); + + List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY); + AnalysisReportDto report = reports.get(0); + + assertThat(reports).hasSize(1); + assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY); + } + + private ComponentDto insertPermissionsForProject(String projectKey) { + ComponentDto project = new ComponentDto().setKey(projectKey); + db.componentDao().insert(session, project); + + tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); + userSession.addProjectPermissions(UserRole.USER, project.key()); + + session.commit(); + + return project; + } + + @Test + public void create_and_book_oldest_available_analysis_report_thrice() { + insertPermissionsForProject(DEFAULT_PROJECT_KEY); + insertPermissionsForProject("2"); + insertPermissionsForProject("3"); + + sut.add(DEFAULT_PROJECT_KEY); + sut.add("2"); + sut.add("3"); + + AnalysisReportDto firstBookedReport = sut.bookNextAvailable(); + AnalysisReportDto secondBookedReport = sut.bookNextAvailable(); + AnalysisReportDto thirdBookedReport = sut.bookNextAvailable(); + + assertThat(firstBookedReport.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(firstBookedReport.getStatus()).isEqualTo(WORKING); + assertThat(secondBookedReport.getProjectKey()).isEqualTo("2"); + assertThat(thirdBookedReport.getProjectKey()).isEqualTo("3"); + } + + @Test + public void search_for_available_report_when_no_report_available() { + AnalysisReportDto nullAnalysisReport = sut.bookNextAvailable(); + + assertThat(nullAnalysisReport).isNull(); + } + + @Test(expected = ForbiddenException.class) + public void cannot_add_report_when_not_the_right_rights() { + ComponentDto project = new ComponentDto() + .setKey("MyProject"); + db.componentDao().insert(session, project); + session.commit(); + + MockUserSession.set().setLogin("gandalf").addProjectPermissions(UserRole.USER, project.key()); + + sut.add(project.getKey()); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskLauncherTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskLauncherTest.java index 91dc9daf7ec..bd2c6d5440c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskLauncherTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskLauncherTest.java @@ -37,10 +37,12 @@ public class AnalysisReportTaskLauncherTest { private AnalysisReportTaskLauncher sut; private ComputationService service; + private AnalysisReportQueue queue; @Before public void before() { this.service = mock(ComputationService.class); + this.queue = mock(AnalysisReportQueue.class); } @After @@ -50,25 +52,25 @@ public class AnalysisReportTaskLauncherTest { @Test public void call_findAndBook_when_launching_a_recurrent_task() throws Exception { - sut = new AnalysisReportTaskLauncher(service, 0, 1, TimeUnit.MILLISECONDS); + sut = new AnalysisReportTaskLauncher(service, queue, 0, 1, TimeUnit.MILLISECONDS); sut.start(); sleep(); - verify(service, atLeastOnce()).findAndBookNextAvailableAnalysisReport(); + verify(queue, atLeastOnce()).bookNextAvailable(); } @Test - public void call_findAndBook_when_executing_task_immediatly() throws Exception { - sut = new AnalysisReportTaskLauncher(service, 1, 1, TimeUnit.HOURS); + public void call_findAndBook_when_executing_task_immediately() throws Exception { + sut = new AnalysisReportTaskLauncher(service, queue, 1, 1, TimeUnit.HOURS); sut.start(); sut.startAnalysisTaskNow(); sleep(); - verify(service, atLeastOnce()).findAndBookNextAvailableAnalysisReport(); + verify(queue, atLeastOnce()).bookNextAvailable(); } private void sleep() throws InterruptedException { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskTest.java index f2205502c2e..3a64afcd131 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportTaskTest.java @@ -31,29 +31,33 @@ public class AnalysisReportTaskTest { private AnalysisReportTask sut; private ComputationService service; + private AnalysisReportQueue queue; @Before public void before() { this.service = mock(ComputationService.class); - this.sut = new AnalysisReportTask(service); + this.queue = mock(AnalysisReportQueue.class); + this.sut = new AnalysisReportTask(queue, service); } @Test public void call_findAndBook_and_no_call_to_analyze_if_no_report_found() { sut.run(); - verify(service).findAndBookNextAvailableAnalysisReport(); + verify(queue).bookNextAvailable(); verify(service, times(0)).analyzeReport(any(AnalysisReportDto.class)); } @Test public void call_findAndBook_and_then_analyze_if_there_is_a_report() { - when(service.findAndBookNextAvailableAnalysisReport()).thenReturn(AnalysisReportDto.newForTests(1L)); + when(queue.bookNextAvailable()).thenReturn(AnalysisReportDto.newForTests(1L)); sut.run(); - verify(service).findAndBookNextAvailableAnalysisReport(); + verify(queue).bookNextAvailable(); verify(service).analyzeReport(any(AnalysisReportDto.class)); } + + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceMediumTest.java index 42c987d437e..3fd74d685c4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceMediumTest.java @@ -39,7 +39,6 @@ import org.sonar.core.user.UserDto; import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.db.DbClient; -import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.issue.IssueQuery; import org.sonar.server.issue.IssueTesting; import org.sonar.server.issue.db.IssueDao; @@ -55,12 +54,12 @@ import org.sonar.server.search.Result; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; +import java.sql.SQLException; import java.util.Date; import java.util.List; import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; -import static org.sonar.core.computation.db.AnalysisReportDto.Status.WORKING; public class ComputationServiceMediumTest { private static final String DEFAULT_PROJECT_KEY = "123456789-987654321"; @@ -70,6 +69,7 @@ public class ComputationServiceMediumTest { private ComputationService sut; + private AnalysisReportQueue queue; private DbClient db; private DbSession session; private MockUserSession userSession; @@ -79,6 +79,7 @@ public class ComputationServiceMediumTest { tester.clearDbAndIndexes(); db = tester.get(DbClient.class); session = db.openSession(false); + queue = tester.get(AnalysisReportQueue.class); sut = tester.get(ComputationService.class); @@ -99,48 +100,15 @@ public class ComputationServiceMediumTest { } @Test - public void create_analysis_report_and_retrieve_it() { - insertPermissionsForProject(DEFAULT_PROJECT_KEY); - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); - - List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY); - AnalysisReportDto report = reports.get(0); - - assertThat(reports).hasSize(1); - assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY); - } - - @Test - public void create_and_book_oldest_available_analysis_report_thrice() { - insertPermissionsForProject(DEFAULT_PROJECT_KEY); - insertPermissionsForProject("2"); - insertPermissionsForProject("3"); - - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); - sut.addAnalysisReport("2"); - sut.addAnalysisReport("3"); - - AnalysisReportDto firstBookedReport = sut.findAndBookNextAvailableAnalysisReport(); - AnalysisReportDto secondBookedReport = sut.findAndBookNextAvailableAnalysisReport(); - AnalysisReportDto thirdBookedReport = sut.findAndBookNextAvailableAnalysisReport(); - - assertThat(firstBookedReport.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY); - assertThat(firstBookedReport.getStatus()).isEqualTo(WORKING); - assertThat(secondBookedReport.getProjectKey()).isEqualTo("2"); - assertThat(thirdBookedReport.getProjectKey()).isEqualTo("3"); - } - - @Test public void analyze_report() { insertPermissionsForProject(DEFAULT_PROJECT_KEY); - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); + queue.add(DEFAULT_PROJECT_KEY); - AnalysisReportDto report = sut.findAndBookNextAvailableAnalysisReport(); + AnalysisReportDto report = queue.bookNextAvailable(); sut.analyzeReport(report); - assertThat(sut.findByProjectKey(DEFAULT_PROJECT_KEY)).isEmpty(); - + assertThat(queue.findByProjectKey(DEFAULT_PROJECT_KEY)).isEmpty(); } private ComponentDto insertPermissionsForProject(String projectKey) { @@ -156,25 +124,6 @@ public class ComputationServiceMediumTest { } @Test - public void search_for_available_report_when_no_report_available() { - AnalysisReportDto nullAnalysisReport = sut.findAndBookNextAvailableAnalysisReport(); - - assertThat(nullAnalysisReport).isNull(); - } - - @Test(expected = ForbiddenException.class) - public void fail_without_global_scan_permission() { - ComponentDto project = new ComponentDto() - .setKey("MyProject"); - db.componentDao().insert(session, project); - session.commit(); - - MockUserSession.set().setLogin("gandalf").addProjectPermissions(UserRole.USER, project.key()); - - sut.addAnalysisReport(project.getKey()); - } - - @Test public void add_issues_in_index() { ComponentDto project = insertPermissionsForProject(DEFAULT_PROJECT_KEY); @@ -194,8 +143,8 @@ public class ComputationServiceMediumTest { clearIssueIndexToSimulateBatchInsertWithoutIndexing(); - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); - List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY); + queue.add(DEFAULT_PROJECT_KEY); + List<AnalysisReportDto> reports = queue.findByProjectKey(DEFAULT_PROJECT_KEY); sut.analyzeReport(reports.get(0)); @@ -207,8 +156,8 @@ public class ComputationServiceMediumTest { public void add_project_issue_permission_in_index() throws Exception { ComponentDto project = insertPermissionsForProject(DEFAULT_PROJECT_KEY); - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); - List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY); + queue.add(DEFAULT_PROJECT_KEY); + List<AnalysisReportDto> reports = queue.findByProjectKey(DEFAULT_PROJECT_KEY); sut.analyzeReport(reports.get(0)); @@ -243,8 +192,8 @@ public class ComputationServiceMediumTest { clearIssueIndexToSimulateBatchInsertWithoutIndexing(); - sut.addAnalysisReport(DEFAULT_PROJECT_KEY); - List<AnalysisReportDto> reports = sut.findByProjectKey(DEFAULT_PROJECT_KEY); + queue.add(DEFAULT_PROJECT_KEY); + List<AnalysisReportDto> reports = queue.findByProjectKey(DEFAULT_PROJECT_KEY); sut.analyzeReport(reports.get(0)); @@ -254,4 +203,9 @@ public class ComputationServiceMediumTest { Result<Issue> issueIndex = tester.get(IssueIndex.class).search(IssueQuery.builder().build(), new QueryContext()); assertThat(issueIndex.getTotal()).isEqualTo(2001); } + + @Test(expected = SQLException.class) + public void exceptions_thrown_are_transmitted() { + + } } 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 deleted file mode 100644 index cad7bd6f077..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package org.sonar.server.computation; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.core.persistence.DbSession; -import org.sonar.server.computation.db.AnalysisReportDao; -import org.sonar.server.db.DbClient; -import org.sonar.server.permission.InternalPermissionService; -import org.sonar.server.search.IndexClient; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - -public class ComputationServiceTest { - - private ComputationService sut; - private DbClient dbClient; - private AnalysisReportDao analysisReportDao; - private DbSession session; - - @Before - public void before() { - analysisReportDao = mock(AnalysisReportDao.class); - dbClient = mock(DbClient.class); - session = mock(DbSession.class); - - when(dbClient.analysisReportDao()).thenReturn(analysisReportDao); - when(dbClient.openSession(false)).thenReturn(session); - - sut = new ComputationService(dbClient, mock(IndexClient.class), mock(InternalPermissionService.class)); - } - - @Test - public void findByProjectKey_call_corresponding_dao() { - sut.findByProjectKey("ANY_STRING"); - verify(analysisReportDao).findByProjectKey(any(DbSession.class), anyString()); - } -} |