diff options
18 files changed, 468 insertions, 23 deletions
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb index a34ac48d079..e8aa7cafb25 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb @@ -6,14 +6,13 @@ options['createdAfter'] = Api::Utils.format_datetime(@dashboard_configuration.from_datetime) options['createdBefore'] = Api::Utils.format_datetime(DateTime.now) end - results = Api.issues.find(options) - issues = results.issues() + results = Internal.issues.findIssueAssignees(options) + assignees = results.results - unless issues.empty? + unless assignees.empty? issues_by_assignee = {} counter_no_assignee = 0 - issues.each do |issue| - assignee = issue.assignee() + assignees.each do |assignee| if assignee counter = issues_by_assignee[assignee] if counter @@ -35,7 +34,7 @@ <h3><%= message('widget.unresolved_issues_per_assignee.name') -%></h3> -<% if issues.size ==0 %> +<% if assignees.size ==0 %> <span class="empty_widget"><%= message('widget.unresolved_issues_per_assignee.name') -%></span> <% else %> diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsColumn.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsColumn.java new file mode 100644 index 00000000000..8e335a021a5 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsColumn.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.issue.db; + +import com.google.common.collect.ImmutableList; + +import java.util.List; + +public class IssueStatsColumn { + + private IssueStatsColumn() { + // utility + } + + public static final String ASSIGNEE = "ASSIGNEE"; + + public static final List<String> ALL = ImmutableList.of(ASSIGNEE); + +} diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsDao.java new file mode 100644 index 00000000000..b5cfc3dfdc8 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsDao.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.issue.db; + +import org.apache.ibatis.session.SqlSession; +import org.sonar.api.ServerComponent; +import org.sonar.api.issue.IssueQuery; +import org.sonar.core.persistence.MyBatis; + +import javax.annotation.Nullable; + +import java.util.List; + +/** + * @since 3.6 + */ +public class IssueStatsDao implements ServerComponent { + + private final MyBatis mybatis; + + public IssueStatsDao(MyBatis mybatis) { + this.mybatis = mybatis; + } + + public List<Object> selectIssuesColumn(IssueQuery query, String column, @Nullable Integer userId) { + SqlSession session = mybatis.openSession(); + try { + IssueStatsMapper mapper = session.getMapper(IssueStatsMapper.class); + return mapper.selectIssuesColumn(query, column, userId, query.requiredRole()); + } finally { + MyBatis.closeQuietly(session); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsMapper.java new file mode 100644 index 00000000000..95c89e48edc --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStatsMapper.java @@ -0,0 +1,33 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.issue.db; + +import org.apache.ibatis.annotations.Param; +import org.sonar.api.issue.IssueQuery; + +import java.util.List; + +public interface IssueStatsMapper { + + List<Object> selectIssuesColumn(@Param("query") IssueQuery query, @Param("column") String column, + @Param("userId") Integer userId, @Param("role") String role); + +} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java index e6ec895fb13..33fa7b7708a 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java @@ -24,10 +24,7 @@ import org.sonar.core.dashboard.ActiveDashboardDao; import org.sonar.core.dashboard.DashboardDao; import org.sonar.core.duplication.DuplicationDao; import org.sonar.core.graph.jdbc.GraphDao; -import org.sonar.core.issue.db.ActionPlanDao; -import org.sonar.core.issue.db.ActionPlanStatsDao; -import org.sonar.core.issue.db.IssueChangeDao; -import org.sonar.core.issue.db.IssueDao; +import org.sonar.core.issue.db.*; import org.sonar.core.measure.MeasureFilterDao; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.purge.PurgeDao; @@ -60,6 +57,7 @@ public final class DaoUtils { DuplicationDao.class, GraphDao.class, IssueDao.class, + IssueStatsDao.class, IssueChangeDao.class, LoadedTemplateDao.class, MeasureFilterDao.class, diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java index 542b29a7cf7..af3619bd53c 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java @@ -120,7 +120,7 @@ public class MyBatis implements BatchComponent, ServerComponent { loadAlias(conf, "ActionPlanStats", ActionPlanStatsDto.class); Class<?>[] mappers = {ActiveDashboardMapper.class, AuthorMapper.class, DashboardMapper.class, - DependencyMapper.class, DuplicationMapper.class, GraphDtoMapper.class, IssueMapper.class, IssueChangeMapper.class, LoadedTemplateMapper.class, + DependencyMapper.class, DuplicationMapper.class, GraphDtoMapper.class, IssueMapper.class, IssueStatsMapper.class, IssueChangeMapper.class, LoadedTemplateMapper.class, MeasureFilterMapper.class, PropertiesMapper.class, PurgeMapper.class, ResourceKeyUpdaterMapper.class, ResourceIndexerMapper.class, ResourceMapper.class, ResourceSnapshotMapper.class, RoleMapper.class, RuleMapper.class, SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, WidgetMapper.class, WidgetPropertyMapper.class, MeasureMapper.class, SnapshotDataMapper.class, diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueStatsMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueStatsMapper.xml new file mode 100644 index 00000000000..beab090bafd --- /dev/null +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueStatsMapper.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd"> + +<mapper namespace="org.sonar.core.issue.db.IssueStatsMapper"> + + <select id="selectIssuesColumn" parameterType="map" resultType="Object" fetchSize="100000"> + select + <if test="'ASSIGNEE'.equals(column)"> + i.assignee + </if> + <include refid="org.sonar.core.issue.db.IssueMapper.selectQueryConditions"/> + </select> + +</mapper>
\ No newline at end of file diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStatsDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStatsDaoTest.java new file mode 100644 index 00000000000..4ce7c628f0b --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStatsDaoTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.core.issue.db; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.issue.IssueQuery; +import org.sonar.core.persistence.AbstractDaoTestCase; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class IssueStatsDaoTest extends AbstractDaoTestCase { + + IssueStatsDao dao; + + @Before + public void createDao() { + dao = new IssueStatsDao(getMyBatis()); + } + + @Test + public void should_select_assignees(){ + setupData("should_select_assignees"); + + IssueQuery query = IssueQuery.builder().requiredRole("user").build(); + List<Object> results = dao.selectIssuesColumn(query, IssueStatsColumn.ASSIGNEE, null); + assertThat(results).hasSize(3); + // 2 perceval, and one null + assertThat(results).containsOnly("perceval", null); + } +} diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStatsDaoTest/should_select_assignees.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStatsDaoTest/should_select_assignees.xml new file mode 100644 index 00000000000..313895235a4 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStatsDaoTest/should_select_assignees.xml @@ -0,0 +1,80 @@ +<dataset> + + <group_roles id="1" group_id="[null]" resource_id="399" role="user"/> + <snapshots id="100" project_id="399" root_snapshot_id="[null]" parent_snapshot_id="[null]" root_project_id="399" path="" islast="[true]" /> + + <issues + id="100" + kee="ABCDE-1" + component_id="401" + root_component_id="399" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="101" + kee="ABCDE-2" + component_id="401" + root_component_id="399" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="[null]" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="102" + kee="ABCDE-3" + component_id="401" + root_component_id="399" + rule_id="501" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="FIXED" + checksum="XXX" + reporter="arthur" + assignee="perceval" + author_login="[null]" + issue_attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> +</dataset> diff --git a/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java index f7682b6693c..fcdf4e5dbd6 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java @@ -32,7 +32,6 @@ import org.sonar.api.user.UserFinder; import org.sonar.api.utils.Paging; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.DefaultIssueComment; -import org.sonar.core.issue.DefaultIssueQueryResult; import org.sonar.core.issue.db.IssueChangeDao; import org.sonar.core.issue.db.IssueDao; import org.sonar.core.issue.db.IssueDto; @@ -93,6 +92,7 @@ public class DefaultIssueFinder implements IssueFinder { return dto.toDefaultIssue(); } + @Override public IssueQueryResult find(IssueQuery query) { LOG.debug("IssueQuery : {}", query); SqlSession sqlSession = myBatis.openSession(); @@ -142,17 +142,14 @@ public class DefaultIssueFinder implements IssueFinder { } } - DefaultIssueQueryResult defaultIssueQueryResult = new DefaultIssueQueryResult(); - defaultIssueQueryResult.setMaxResultsReached(authorizedIssues.size() == query.maxResults()); - defaultIssueQueryResult.setIssues(issues) + return new DefaultIssueQueryResult(issues) + .setMaxResultsReached(authorizedIssues.size() == query.maxResults()) .addRules(findRules(ruleIds)) .addComponents(findComponents(componentIds)) .addProjects(findProjects(projectIds)) .addActionPlans(findActionPlans(actionPlanKeys)) .addUsers(findUsers(users)) .setPaging(paging); - - return defaultIssueQueryResult; } finally { MyBatis.closeQuietly(sqlSession); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueQueryResult.java b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java index aabd51bca84..4a404362024 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueQueryResult.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.core.issue; +package org.sonar.server.issue; import com.google.common.collect.Maps; import org.sonar.api.component.Component; @@ -47,9 +47,8 @@ public class DefaultIssueQueryResult implements IssueQueryResult { private boolean maxResultsReached; private Paging paging; - public DefaultIssueQueryResult setIssues(List<Issue> issues){ + public DefaultIssueQueryResult(List<Issue> issues){ this.issues = issues; - return this; } public DefaultIssueQueryResult addRules(Collection<Rule> rules){ diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index c81de2d16df..b6ee9e55fdc 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -55,18 +55,24 @@ public class InternalRubyIssueService implements ServerComponent { private final IssueService issueService; private final IssueCommentService commentService; private final ActionPlanService actionPlanService; + private final IssueStatsFinder issueStatsFinder; private final ResourceDao resourceDao; public InternalRubyIssueService(IssueService issueService, IssueCommentService commentService, ActionPlanService actionPlanService, - ResourceDao resourceDao) { + IssueStatsFinder issueStatsFinder, ResourceDao resourceDao) { this.issueService = issueService; this.commentService = commentService; this.actionPlanService = actionPlanService; + this.issueStatsFinder = issueStatsFinder; this.resourceDao = resourceDao; } + public IssueStatsFinder.IssueStatsResult findIssueAssignees(Map<String, Object> params){ + return issueStatsFinder.findIssueAssignees(PublicRubyIssueService.toQuery(params)); + } + public List<Transition> listTransitions(String issueKey) { return issueService.listTransitions(issueKey); } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java new file mode 100644 index 00000000000..a19829113f0 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java @@ -0,0 +1,92 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.issue; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.sonar.api.ServerComponent; +import org.sonar.api.issue.IssueQuery; +import org.sonar.api.user.User; +import org.sonar.api.user.UserFinder; +import org.sonar.core.issue.db.IssueStatsColumn; +import org.sonar.core.issue.db.IssueStatsDao; +import org.sonar.server.platform.UserSession; + +import javax.annotation.CheckForNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class IssueStatsFinder implements ServerComponent { + + private final IssueStatsDao issuestatsDao; + private final UserFinder userFinder; + + public IssueStatsFinder(IssueStatsDao issuestatsDao, UserFinder userFinder) { + this.issuestatsDao = issuestatsDao; + this.userFinder = userFinder; + } + + public IssueStatsResult findIssueAssignees(IssueQuery query) { + List<Object> results = issuestatsDao.selectIssuesColumn(query, IssueStatsColumn.ASSIGNEE, UserSession.get().userId()); + + Set<String> users = Sets.newHashSet(); + for (Object result : results) { + if (result != null) { + users.add((String) result); + } + } + + return new IssueStatsResult(results).addUsers(findUsers(users)); + } + + private Collection<User> findUsers(Set<String> logins) { + return userFinder.findByLogins(Lists.newArrayList(logins)); + } + + public static class IssueStatsResult { + private final Map<String, User> usersByLogin = Maps.newHashMap(); + private List<Object> results; + + public IssueStatsResult(List<Object> results) { + this.results = results; + } + + public IssueStatsResult addUsers(Collection<User> users) { + for (User user : users) { + usersByLogin.put(user.login(), user); + } + return this; + } + + public List<Object> results() { + return results; + } + + @CheckForNull + public User user(String login) { + return usersByLogin.get(login); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java index 0b8909dd1d0..1832775006f 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java @@ -63,7 +63,7 @@ public class PublicRubyIssueService implements RubyIssueService { return finder.find(toQuery(params)); } - IssueQuery toQuery(Map<String, Object> props) { + static IssueQuery toQuery(Map<String, Object> props) { IssueQuery.Builder builder = IssueQuery.builder(); builder.requiredRole(UserRole.CODEVIEWER); builder.issueKeys(RubyUtils.toStrings(props.get("issues"))); diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index a1605e29579..0691c29d5f2 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -263,6 +263,7 @@ public final class Platform { servicesContainer.addSingleton(IssueService.class); servicesContainer.addSingleton(IssueCommentService.class); servicesContainer.addSingleton(DefaultIssueFinder.class); + servicesContainer.addSingleton(IssueStatsFinder.class); servicesContainer.addSingleton(PublicRubyIssueService.class); servicesContainer.addSingleton(InternalRubyIssueService.class); servicesContainer.addSingleton(ActionPlanService.class); diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java index d3419a8082e..0123c9f1083 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.issue; +import com.google.common.collect.Lists; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import org.sonar.api.component.Component; @@ -27,6 +28,7 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueQuery; import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.rules.Rule; +import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.DefaultActionPlan; @@ -37,6 +39,7 @@ import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.core.user.AuthorizationDao; +import org.sonar.core.user.DefaultUser; import java.util.Collections; import java.util.List; @@ -48,6 +51,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyCollection; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.anyListOf; import static org.mockito.Mockito.*; public class DefaultIssueFinderTest { @@ -242,6 +246,32 @@ public class DefaultIssueFinderTest { } @Test + public void should_get_user_from_result() { + when(userFinder.findByLogins(anyListOf(String.class))).thenReturn(Lists.<User>newArrayList( + new DefaultUser().setLogin("perceval").setName("Perceval"), + new DefaultUser().setLogin("arthur").setName("Roi Arthur") + )); + + IssueQuery query = IssueQuery.builder().build(); + + IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setComponentId(123).setRootComponentId(100).setKee("ABC").setAssignee("perceval") + .setRuleKey_unit_test_only("squid", "AvoidCycle") + .setStatus("OPEN").setResolution("OPEN"); + IssueDto issue2 = new IssueDto().setId(2L).setRuleId(50).setComponentId(123).setRootComponentId(100).setKee("DEF").setReporter("arthur") + .setRuleKey_unit_test_only("squid", "AvoidCycle") + .setStatus("OPEN").setResolution("OPEN"); + List<IssueDto> dtoList = newArrayList(issue1, issue2); + when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); + + IssueQueryResult results = finder.find(query); + assertThat(results.issues()).hasSize(2); + + assertThat(results.users()).hasSize(2); + assertThat(results.user("perceval").name()).isEqualTo("Perceval"); + assertThat(results.user("arthur").name()).isEqualTo("Roi Arthur"); + } + + @Test public void should_get_empty_result_when_no_issue() { IssueQuery query = IssueQuery.builder().build(); when(issueDao.selectIssues(eq(query), anyInt(), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java index 24e5ebabe0c..f49177d8989 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java @@ -43,12 +43,13 @@ public class InternalRubyIssueServiceTest { private IssueCommentService commentService = mock(IssueCommentService.class); private ActionPlanService actionPlanService = mock(ActionPlanService.class); private ResourceDao resourceDao = mock(ResourceDao.class); + private IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class); @Before public void before() { ResourceDto project = new ResourceDto().setKey("org.sonar.Sample"); when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project); - internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, resourceDao); + internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, issueStatsFinder, resourceDao); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java new file mode 100644 index 00000000000..15497ff2c2a --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java @@ -0,0 +1,54 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.issue; + +import com.google.common.collect.Lists; +import org.junit.Test; +import org.sonar.api.issue.IssueQuery; +import org.sonar.api.user.User; +import org.sonar.api.user.UserFinder; +import org.sonar.core.issue.db.IssueStatsDao; +import org.sonar.core.user.DefaultUser; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class IssueStatsFinderTest { + + private IssueStatsDao issuestatsDao = mock(IssueStatsDao.class); + private UserFinder userFinder = mock(UserFinder.class); + + @Test + public void should_find_assignees(){ + when(issuestatsDao.selectIssuesColumn(any(IssueQuery.class), anyString(), anyInt())).thenReturn(Lists.<Object>newArrayList("perceval", "perceval", "arthur", null)); + when(userFinder.findByLogins(anyListOf(String.class))).thenReturn(Lists.<User>newArrayList( + new DefaultUser().setLogin("perceval").setName("Perceval"), + new DefaultUser().setLogin("arthur").setName("Roi Arthur") + )); + + IssueStatsFinder issueStatsFinder = new IssueStatsFinder(issuestatsDao, userFinder); + IssueStatsFinder.IssueStatsResult issueStatsResult = issueStatsFinder.findIssueAssignees(IssueQuery.builder().build()); + assertThat(issueStatsResult.results()).hasSize(4); + assertThat(issueStatsResult.user("arthur").name()).isEqualTo("Roi Arthur"); + } +} |