private Integer snapshotId;
+ private String textValue;
+
private byte[] data;
public Integer getId() {
return this;
}
- public byte[] getData() {
- return data;
- }
-
public MeasureDataDto setData(byte[] data) {
this.data = data;
return this;
}
@CheckForNull
- public String getText() {
+ public String getData() {
if (data != null) {
return new String(data, Charsets.UTF_8);
}
- return null;
+ return textValue;
}
}
<sql id="measureDataColumns">
pm.id,
pm.snapshot_id as snapshotId,
+ pm.text_value as textValue,
pm.measure_data as data
</sql>
}
@Test
- public void find_by_component_key_and_metric_key() throws Exception {
+ public void find_data_by_component_key_and_metric_key() throws Exception {
setupData("shared");
MeasureDataDto result = dao.findByComponentKeyAndMetricKey("org.sonar.core.measure.db.MeasureData", "authors_by_line");
assertThat(result.getId()).isEqualTo(20);
assertThat(result.getSnapshotId()).isEqualTo(5);
- assertThat(result.getText()).isNotNull();
assertThat(result.getData()).isNotNull();
- assertThat(result.getText()).isEqualTo("0123456789012345678901234567890123456789");
+ assertThat(result.getData()).isEqualTo("0123456789012345678901234567890123456789");
}
@Test
- public void find_by_component_key_and_metric_key_without_text() throws Exception {
- setupData("find_by_component_key_and_metric_key_without_text");
+ public void find_text_value_by_component_key_and_metric_key() throws Exception {
+ setupData("shared");
- MeasureDataDto result = dao.findByComponentKeyAndMetricKey("org.sonar.core.measure.db.MeasureData", "authors_by_line");
- assertThat(result.getId()).isEqualTo(20);
+ MeasureDataDto result = dao.findByComponentKeyAndMetricKey("org.sonar.core.measure.db.MeasureData", "coverage_line_hits_data");
+ assertThat(result.getId()).isEqualTo(21);
assertThat(result.getSnapshotId()).isEqualTo(5);
- assertThat(result.getText()).isNull();
- assertThat(result.getData()).isNull();
+ assertThat(result.getData()).isEqualTo("36=1;37=1;38=1;39=1;43=1;48=1;53=1");
}
}
+
+++ /dev/null
-<dataset>
-
- <metrics id="10" name="authors_by_line"/>
- <projects id="1" kee="org.sonar.core.measure.db.MeasureData" enabled="[true]"/>
- <snapshots id="5" project_id="1" islast="[true]" />
-
- <project_measures id="20" snapshot_id="5" metric_id="10" measure_data="[null]"/>
-
-</dataset>
<dataset>
<metrics id="10" name="authors_by_line"/>
+ <metrics id="11" name="coverage_line_hits_data"/>
+
<projects id="1" kee="org.sonar.core.measure.db.MeasureData" enabled="[true]"/>
+
<snapshots id="5" project_id="1" islast="[true]" />
- <project_measures id="20" snapshot_id="5" metric_id="10" measure_data="MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ=="/>
+ <project_measures id="20" snapshot_id="5" metric_id="10" text_value="[null]" measure_data="MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ=="/>
+ <project_measures id="21" snapshot_id="5" metric_id="11" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" measure_data="[null]"/>
</dataset>
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.persistence.PreviewDatabaseFactory;
-import org.sonar.core.persistence.SemaphoreUpdater;
-import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.persistence.*;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.server.db.EmbeddedDatabaseFactory;
import org.sonar.server.db.migrations.DatabaseMigrations;
import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
-import org.sonar.server.debt.DebtModelBackup;
-import org.sonar.server.debt.DebtModelLookup;
-import org.sonar.server.debt.DebtModelOperations;
-import org.sonar.server.debt.DebtModelPluginRepository;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.debt.DebtModelXMLExporter;
-import org.sonar.server.debt.DebtRulesXMLImporter;
+import org.sonar.server.debt.*;
import org.sonar.server.es.ESIndex;
import org.sonar.server.es.ESNode;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.AssignAction;
-import org.sonar.server.issue.CommentAction;
-import org.sonar.server.issue.DefaultIssueFinder;
-import org.sonar.server.issue.InternalRubyIssueService;
-import org.sonar.server.issue.IssueBulkChangeService;
-import org.sonar.server.issue.IssueChangelogFormatter;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.IssueStatsFinder;
-import org.sonar.server.issue.PlanAction;
-import org.sonar.server.issue.PublicRubyIssueService;
-import org.sonar.server.issue.ServerIssueStorage;
-import org.sonar.server.issue.SetSeverityAction;
-import org.sonar.server.issue.TransitionAction;
+import org.sonar.server.issue.*;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.actionplan.ActionPlanWs;
import org.sonar.server.issue.filter.IssueFilterService;
import org.sonar.server.platform.ws.RestartHandler;
import org.sonar.server.platform.ws.ServerWs;
import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.plugins.BatchWs;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.ServerPluginJarInstaller;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterClient;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.QGatesAppAction;
-import org.sonar.server.qualitygate.ws.QGatesCopyAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
-import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
-import org.sonar.server.qualitygate.ws.QGatesListAction;
-import org.sonar.server.qualitygate.ws.QGatesRenameAction;
-import org.sonar.server.qualitygate.ws.QGatesSearchAction;
-import org.sonar.server.qualitygate.ws.QGatesSelectAction;
-import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesShowAction;
-import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesWs;
-import org.sonar.server.qualityprofile.ActiveRuleService;
-import org.sonar.server.qualityprofile.DefaultProfilesCache;
-import org.sonar.server.qualityprofile.ESActiveRule;
-import org.sonar.server.qualityprofile.ProfilesManager;
-import org.sonar.server.qualityprofile.QProfileActiveRuleOperations;
-import org.sonar.server.qualityprofile.QProfileBackup;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileOperations;
-import org.sonar.server.qualityprofile.QProfileProjectLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonar.server.qualityprofile.QProfileRepositoryExporter;
-import org.sonar.server.qualityprofile.QProfileRuleLookup;
-import org.sonar.server.qualityprofile.QProfiles;
+import org.sonar.server.qualitygate.ws.*;
+import org.sonar.server.qualityprofile.*;
import org.sonar.server.qualityprofile.RegisterQualityProfiles;
-import org.sonar.server.qualityprofile.RuleActivationContextFactory;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
import org.sonar.server.qualityprofile.persistence.ActiveRuleDao;
import org.sonar.server.qualityprofile.ws.QProfileRecreateBuiltInAction;
import org.sonar.server.qualityprofile.ws.QProfilesWs;
import org.sonar.server.qualityprofile.ws.RuleActivationActions;
-import org.sonar.server.rule.DeprecatedRulesDefinition;
-import org.sonar.server.rule.ESRuleTags;
-import org.sonar.server.rule.RubyRuleService;
-import org.sonar.server.rule.RuleDefinitionsLoader;
-import org.sonar.server.rule.RuleOperations;
-import org.sonar.server.rule.RuleRegistry;
-import org.sonar.server.rule.RuleRepositories;
-import org.sonar.server.rule.RuleTagLookup;
-import org.sonar.server.rule.RuleTagOperations;
-import org.sonar.server.rule.RuleTags;
-import org.sonar.server.rule.Rules;
-import org.sonar.server.rule.ws.AddTagsWsHandler;
-import org.sonar.server.rule.ws.RemoveTagsWsHandler;
-import org.sonar.server.rule.ws.RuleSearchWsHandler;
-import org.sonar.server.rule.ws.RuleShowWsHandler;
-import org.sonar.server.rule.ws.RuleTagsWs;
-import org.sonar.server.rule.ws.RulesWs;
+import org.sonar.server.rule.*;
+import org.sonar.server.rule.ws.*;
import org.sonar.server.rule2.RegisterRules;
import org.sonar.server.rule2.RuleService;
import org.sonar.server.rule2.index.RuleIndex;
import org.sonar.server.rule2.ws.SearchAction;
import org.sonar.server.rule2.ws.SetTagsAction;
import org.sonar.server.rule2.ws.TagsAction;
-import org.sonar.server.search.IndexUtils;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.source.DeprecatedSourceDecorator;
import org.sonar.server.source.HtmlSourceDecorator;
import org.sonar.server.source.ws.ScmWriter;
import org.sonar.server.source.ws.ShowAction;
import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.CleanPreviewAnalysisCache;
-import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-import org.sonar.server.startup.JdbcDriverDeployer;
-import org.sonar.server.startup.LogServerId;
-import org.sonar.server.startup.RegisterDashboards;
-import org.sonar.server.startup.RegisterDebtModel;
-import org.sonar.server.startup.RegisterMetrics;
-import org.sonar.server.startup.RegisterNewMeasureFilters;
-import org.sonar.server.startup.RegisterPermissionTemplates;
-import org.sonar.server.startup.RegisterServletFilters;
-import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
-import org.sonar.server.startup.ServerMetadataPersister;
+import org.sonar.server.startup.*;
+import org.sonar.server.test.CoverageService;
+import org.sonar.server.test.ws.CoverageShowAction;
+import org.sonar.server.test.ws.CoverageWs;
import org.sonar.server.test.ws.TestsWs;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
import org.sonar.server.ui.PageDecorations;
import org.sonar.server.ui.Views;
import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.DefaultUserService;
-import org.sonar.server.user.DoPrivileged;
-import org.sonar.server.user.GroupMembershipFinder;
-import org.sonar.server.user.GroupMembershipService;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.*;
import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.BooleanTypeValidation;
-import org.sonar.server.util.FloatTypeValidation;
-import org.sonar.server.util.IntegerTypeValidation;
-import org.sonar.server.util.StringListTypeValidation;
-import org.sonar.server.util.StringTypeValidation;
-import org.sonar.server.util.TextTypeValidation;
-import org.sonar.server.util.TypeValidations;
+import org.sonar.server.util.*;
import org.sonar.server.ws.ListingWs;
import org.sonar.server.ws.WebServiceEngine;
// Tests
pico.addSingleton(TestsWs.class);
+ pico.addSingleton(CoverageService.class);
+ pico.addSingleton(CoverageWs.class);
+ pico.addSingleton(CoverageShowAction.class);
// graphs and perspective related classes
pico.addSingleton(TestablePerspectiveLoader.class);
import org.sonar.api.web.UserRole;
import org.sonar.core.measure.db.MeasureDataDao;
import org.sonar.core.measure.db.MeasureDataDto;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.util.List;
public class SourceService implements ServerComponent {
*/
private final DeprecatedSourceDecorator deprecatedSourceDecorator;
- private final ResourceDao resourceDao;
private final MeasureDataDao measureDataDao;
- public SourceService(HtmlSourceDecorator sourceDecorator, DeprecatedSourceDecorator deprecatedSourceDecorator, ResourceDao resourceDao, MeasureDataDao measureDataDao) {
+ public SourceService(HtmlSourceDecorator sourceDecorator, DeprecatedSourceDecorator deprecatedSourceDecorator, MeasureDataDao measureDataDao) {
this.sourceDecorator = sourceDecorator;
this.deprecatedSourceDecorator = deprecatedSourceDecorator;
- this.resourceDao = resourceDao;
this.measureDataDao = measureDataDao;
}
}
public void checkPermission(String fileKey) {
- ResourceDto project = resourceDao.getRootProjectByComponentKey(fileKey);
- if (project == null) {
- throw new NotFoundException("File does not exist");
- }
- UserSession.get().checkProjectPermission(UserRole.CODEVIEWER, project.getKey());
+ UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
}
/**
private String findDataFromComponent(String fileKey, String metricKey) {
MeasureDataDto data = measureDataDao.findByComponentKeyAndMetricKey(fileKey, metricKey);
if (data != null) {
- return data.getText();
+ return data.getData();
}
return null;
}
void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("scm")
- .setDescription("Get SCM information of source files")
+ .setDescription("Get SCM information of source files. Require Browse permission on file's project")
.setSince("4.4")
.setResponseExample(Resources.getResource(getClass(), "example-scm.json"))
.setHandler(this);
action
.createParam("from")
- .setDescription("First line to return. Starts at 1.")
+ .setDescription("First line to return. Starts at 1")
.setExampleValue("10")
.setDefaultValue("1");
*/
package org.sonar.server.source.ws;
-import com.google.common.base.Splitter;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.KeyValueFormat;
import org.sonar.api.utils.text.JsonWriter;
import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
+import java.util.Map;
public class ScmWriter implements ServerComponent {
- void write(@Nullable String authorsData, @Nullable String datesDate, int from, int to, boolean group, JsonWriter json) {
+ void write(@Nullable String authorsData, @Nullable String datesData, int from, int to, boolean group, JsonWriter json) {
json.name("scm").beginArray();
if (authorsData != null) {
- List<String> authors = splitLine(authorsData);
- List<String> dates = splitLine(datesDate);
+ Map<Integer, String> authors = KeyValueFormat.parseIntString(authorsData);
+ Map<Integer, String> dates = KeyValueFormat.parseIntString(datesData);
String previousAuthor = null;
String previousDate = null;
boolean started = false;
- for (int i = 0; i < authors.size(); i++) {
- String[] authorWithLine = splitColumn(authors.get(i));
- Integer line = Integer.parseInt(authorWithLine[0]);
- String author = authorWithLine[1];
-
- String[] dateWithLine = splitColumn(dates.get(i));
- String date = dateWithLine[1];
+ for (Map.Entry<Integer, String> entry : authors.entrySet()) {
+ Integer line = entry.getKey();
+ String author = entry.getValue();
+ String date = dates.get(line);
String formattedDate = DateUtils.formatDate(DateUtils.parseDateTime(date));
if (line >= from && line <= to) {
if (!started || !group || !isSameCommit(date, previousDate, author, previousAuthor)) {
json.endArray();
}
- private List<String> splitLine(@Nullable String line) {
- if (line == null) {
- return Collections.emptyList();
- }
- return newArrayList(Splitter.on(";").omitEmptyStrings().split(line));
- }
-
- private String[] splitColumn(String column) {
- return column.split("=");
- }
-
private boolean isSameCommit(String date, String previousDate, String author, String previousAuthor) {
return author.equals(previousAuthor) && date.equals(previousDate);
}
void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("show")
- .setDescription("Get source code")
+ .setDescription("Get source code. Require Browse permission on file's project")
.setSince("4.4")
.setResponseExample(Resources.getResource(getClass(), "example-show.json"))
.setHandler(this);
--- /dev/null
+/*
+ * 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.test;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.measure.db.MeasureDataDao;
+import org.sonar.core.measure.db.MeasureDataDto;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.CheckForNull;
+
+public class CoverageService implements ServerComponent {
+
+ private final MeasureDataDao measureDataDao;
+
+ public CoverageService(MeasureDataDao measureDataDao) {
+ this.measureDataDao = measureDataDao;
+ }
+
+ public void checkPermission(String fileKey) {
+ UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
+ }
+
+ /**
+ * Warning - does not check permission
+ */
+ @CheckForNull
+ public String getHitsData(String fileKey) {
+ return findDataFromComponent(fileKey, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY);
+ }
+
+ /**
+ * Warning - does not check permission
+ */
+ @CheckForNull
+ public String getConditionsData(String fileKey) {
+ return findDataFromComponent(fileKey, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
+ }
+
+ /**
+ * Warning - does not check permission
+ */
+ @CheckForNull
+ public String getCoveredConditionsData(String fileKey) {
+ return findDataFromComponent(fileKey, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
+ }
+
+ @CheckForNull
+ private String findDataFromComponent(String fileKey, String metricKey) {
+ MeasureDataDto data = measureDataDao.findByComponentKeyAndMetricKey(fileKey, metricKey);
+ if (data != null) {
+ return data.getData();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * 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.test.ws;
+
+import com.google.common.io.Resources;
+import org.apache.commons.lang.ObjectUtils;
+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.api.utils.KeyValueFormat;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.test.CoverageService;
+
+import java.util.Map;
+
+public class CoverageShowAction implements RequestHandler {
+
+ private final CoverageService coverageService;
+
+ public CoverageShowAction(CoverageService coverageService) {
+ this.coverageService = coverageService;
+ }
+
+ void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("show")
+ .setDescription("Get code coverage. Require Browse permission on file's project")
+ .setSince("4.4")
+ .setResponseExample(Resources.getResource(getClass(), "coverage-example-show.json"))
+ .setHandler(this);
+
+ action
+ .createParam("key")
+ .setRequired(true)
+ .setDescription("File key")
+ .setExampleValue("my_project:/src/foo/Bar.php");
+
+ action
+ .createParam("from")
+ .setDescription("First line to return. Starts at 1")
+ .setExampleValue("10")
+ .setDefaultValue("1");
+
+ action
+ .createParam("to")
+ .setDescription("Last line to return (inclusive)")
+ .setExampleValue("20");
+
+ action
+ .createParam("type")
+ .setDescription("Type of coverage info to return :" +
+ "<ul>" +
+ "<li>UT : Unit Tests</li>" +
+ "<li>IT : Integration Tests</li>" +
+ "<li>OVERALL : Unit and Integration Tests</li>" +
+ "</ul>")
+ .setPossibleValues("UT", "IT", "OVERALL");
+ }
+
+ @Override
+ public void handle(Request request, Response response) {
+ String fileKey = request.mandatoryParam("key");
+ coverageService.checkPermission(fileKey);
+
+ int from = Math.max(request.mandatoryParamAsInt("from"), 1);
+ int to = (Integer) ObjectUtils.defaultIfNull(request.paramAsInt("to"), Integer.MAX_VALUE);
+
+ JsonWriter json = response.newJsonWriter().beginObject();
+
+ String hits = coverageService.getHitsData(fileKey);
+ if (hits != null) {
+ Map<Integer, Integer> hitsByLine = KeyValueFormat.parseIntInt(hits);
+ writeCoverage(hitsByLine, from, to, json);
+ }
+
+ json.endObject().close();
+ }
+
+ private void writeCoverage(Map<Integer, Integer> hitsByLine, int from, int to, JsonWriter json) {
+ json.name("coverage").beginArray();
+ for (Map.Entry<Integer, Integer> entry : hitsByLine.entrySet()) {
+ Integer line = entry.getKey();
+ if (line >= from && line <= to) {
+ Integer hits = entry.getValue();
+ json.beginArray();
+ json.value(line);
+ json.value(hits);
+ json.endArray();
+ }
+ }
+ json.endArray();
+ }
+}
--- /dev/null
+/*
+ * 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.test.ws;
+
+import org.sonar.api.server.ws.WebService;
+
+public class CoverageWs implements WebService {
+
+ private final CoverageShowAction showAction;
+
+ public CoverageWs(CoverageShowAction showAction) {
+ this.showAction = showAction;
+ }
+
+ @Override
+ public void define(Context context) {
+ NewController controller = context.createController("api/coverage")
+ .setSince("4.4")
+ .setDescription("Display coverage information");
+
+ showAction.define(controller);
+
+ controller.done();
+ }
+
+}
.setSince("3.5")
.setInternal(true)
.setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(this.getClass(), "example-plan.json"));
+ .setResponseExample(Resources.getResource(this.getClass(), "tests-example-plan.json"));
action.createParam("resource")
.setRequired(true)
.setSince("3.5")
.setInternal(true)
.setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(this.getClass(), "example-testable.json"));
+ .setResponseExample(Resources.getResource(this.getClass(), "tests-example-testable.json"));
action.createParam("resource")
.setRequired(true)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
import org.sonar.core.user.AuthorizationDao;
import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.platform.Platform;
return this;
}
+ /**
+ * Ensures that user implies the specified project permission on a component. If not a {@link org.sonar.server.exceptions.ForbiddenException} is thrown.
+ */
+ public UserSession checkComponentPermission(String projectPermission, String componentKey) {
+ ResourceDto project = resourceDao().getRootProjectByComponentKey(componentKey);
+ if (project == null) {
+ throw new NotFoundException(String.format("Component '%s' does not exist", componentKey));
+ }
+ return checkProjectPermission(projectPermission, project.getKey());
+ }
+
/**
* Does the user have the given project permission ?
*/
return Platform.component(AuthorizationDao.class);
}
+ ResourceDao resourceDao() {
+ return Platform.component(ResourceDao.class);
+ }
+
public static UserSession get() {
return Objects.firstNonNull(THREAD_LOCAL.get(), ANONYMOUS);
}
--- /dev/null
+{
+ "coverage": [
+ [
+ 36,
+ 1
+ ],
+ [
+ 37,
+ 1
+ ],
+ [
+ 38,
+ 1
+ ],
+ [
+ 39,
+ 1
+ ],
+ [
+ 43,
+ 1
+ ],
+ [
+ 48,
+ 1
+ ],
+ [
+ 53,
+ 1
+ ]
+ ]
+
+}
+++ /dev/null
-{
- "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/test/java/org/sonar/plugins/cpd/SonarBridgeEngineTest.java",
- "name": "SonarBridgeEngineTest.java",
- "longName": "src/test/java/org/sonar/plugins/cpd/SonarBridgeEngineTest.java",
- "testCases": [
- {
- "name": "shouldReturnDefaultBlockSize",
- "type": "UNIT",
- "durationInMs": 2,
- "status": "OK",
- "coverages": [
- {
- "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
- "name": "SonarBridgeEngine.java",
- "longName": "src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
- "lines": [
- 68,
- 69,
- 70,
- 71,
- 72,
- 73,
- 155,
- 156,
- 157,
- 158,
- 160
- ]
- },
- {
- "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/CpdEngine.java",
- "name": "CpdEngine.java",
- "longName": "src/main/java/org/sonar/plugins/cpd/CpdEngine.java",
- "lines": [
- 27
- ]
- }
- ]
- }
- ]
-}
+++ /dev/null
-{
- "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
- "name": "SonarBridgeEngine.java",
- "longName": "src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
- "coveredLines": [
- 56,
- 68,
- 69,
- 70,
- 71,
- 72,
- 73,
- 76,
- 77,
- 146,
- 147,
- 148,
- 150,
- 155,
- 156,
- 157,
- 158,
- 160,
- 166,
- 167,
- 168,
- 170,
- 171,
- 174
- ],
- "coverages": [
- {
- "lines": [
- 68,
- 69,
- 70,
- 71,
- 72,
- 73,
- 76,
- 77
- ],
- "name": "test_engine",
- "status": "OK",
- "durationInMs": 2,
- "testPlan": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java"
- }
- ]
-}
--- /dev/null
+{
+ "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/test/java/org/sonar/plugins/cpd/SonarBridgeEngineTest.java",
+ "name": "SonarBridgeEngineTest.java",
+ "longName": "src/test/java/org/sonar/plugins/cpd/SonarBridgeEngineTest.java",
+ "testCases": [
+ {
+ "name": "shouldReturnDefaultBlockSize",
+ "type": "UNIT",
+ "durationInMs": 2,
+ "status": "OK",
+ "coverages": [
+ {
+ "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
+ "name": "SonarBridgeEngine.java",
+ "longName": "src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
+ "lines": [
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 155,
+ 156,
+ 157,
+ 158,
+ 160
+ ]
+ },
+ {
+ "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/CpdEngine.java",
+ "name": "CpdEngine.java",
+ "longName": "src/main/java/org/sonar/plugins/cpd/CpdEngine.java",
+ "lines": [
+ 27
+ ]
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "key": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
+ "name": "SonarBridgeEngine.java",
+ "longName": "src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java",
+ "coveredLines": [
+ 56,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 76,
+ 77,
+ 146,
+ 147,
+ 148,
+ 150,
+ 155,
+ 156,
+ 157,
+ 158,
+ 160,
+ 166,
+ 167,
+ 168,
+ 170,
+ 171,
+ 174
+ ],
+ "coverages": [
+ {
+ "lines": [
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 76,
+ 77
+ ],
+ "name": "test_engine",
+ "status": "OK",
+ "durationInMs": 2,
+ "testPlan": "org.codehaus.sonar.plugins:sonar-cpd-plugin:src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java"
+ }
+ ]
+}
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.web.UserRole;
import org.sonar.core.measure.db.MeasureDataDao;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.MockUserSession;
HtmlSourceDecorator sourceDecorator;
@Mock
- DeprecatedSourceDecorator deprecatedSourceDecorator;;
-
- @Mock
- ResourceDao resourceDao;
+ DeprecatedSourceDecorator deprecatedSourceDecorator;
@Mock
MeasureDataDao measureDataDao;
@Before
public void setUp() throws Exception {
- service = new SourceService(sourceDecorator, deprecatedSourceDecorator, resourceDao, measureDataDao);
+ service = new SourceService(sourceDecorator, deprecatedSourceDecorator, measureDataDao);
}
@Test
public void get_lines() throws Exception {
String projectKey = "org.sonar.sample";
String componentKey = "org.sonar.sample:Sample";
- MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey);
- when(resourceDao.getRootProjectByComponentKey(componentKey)).thenReturn(new ResourceDto().setKey(projectKey));
+ MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey).addComponent(componentKey, projectKey);
service.getLinesAsHtml(componentKey);
String projectKey = "org.sonar.sample";
String componentKey = "org.sonar.sample:Sample";
MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey);
- when(resourceDao.getRootProjectByComponentKey(componentKey)).thenReturn(null);
try {
service.getLinesAsHtml(componentKey);
public void get_block_of_lines() throws Exception {
String projectKey = "org.sonar.sample";
String componentKey = "org.sonar.sample:Sample";
- MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey);
- when(resourceDao.getRootProjectByComponentKey(componentKey)).thenReturn(new ResourceDto().setKey(projectKey));
+ MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey).addComponent(componentKey, projectKey);;
service.getLinesAsHtml(componentKey, 1, 2);
public void get_lines_from_deprecated_source_decorator_when_no_data_from_new_decorator() throws Exception {
String projectKey = "org.sonar.sample";
String componentKey = "org.sonar.sample:Sample";
- MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey);
- when(resourceDao.getRootProjectByComponentKey(componentKey)).thenReturn(new ResourceDto().setKey(projectKey));
+ MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey).addComponent(componentKey, projectKey);;
when(sourceDecorator.getDecoratedSourceAsHtml(eq(componentKey), anyInt(), anyInt())).thenReturn(Collections.<String>emptyList());
service.getLinesAsHtml(componentKey, 1, 2);
--- /dev/null
+/*
+ * 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.test;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.measure.db.MeasureDataDao;
+import org.sonar.server.user.MockUserSession;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CoverageServiceTest {
+
+ @org.junit.Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Mock
+ MeasureDataDao measureDataDao;
+
+ static final String COMPONENT_KEY = "org.sonar.sample:Sample";
+
+ CoverageService service;
+
+ @Before
+ public void setUp() throws Exception {
+ service = new CoverageService(measureDataDao);
+ }
+
+ @Test
+ public void check_permission() throws Exception {
+ String projectKey = "org.sonar.sample";
+ MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey);
+ MockUserSession.set().addProjectPermissions(UserRole.CODEVIEWER, projectKey).addComponent(COMPONENT_KEY, projectKey);
+
+ service.checkPermission(COMPONENT_KEY);
+ }
+
+ @Test
+ public void get_hits_data() throws Exception {
+ service.getHitsData(COMPONENT_KEY);
+ verify(measureDataDao).findByComponentKeyAndMetricKey(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY);
+ }
+
+ @Test
+ public void not_get_hits_data_if_no_data() throws Exception {
+ when(measureDataDao.findByComponentKeyAndMetricKey(eq(COMPONENT_KEY), anyString())).thenReturn(null);
+ assertThat(service.getHitsData(COMPONENT_KEY)).isNull();
+ }
+
+ @Test
+ public void get_conditions_data() throws Exception {
+ service.getConditionsData(COMPONENT_KEY);
+ verify(measureDataDao).findByComponentKeyAndMetricKey(COMPONENT_KEY, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
+ }
+
+ @Test
+ public void get_coverered_conditions_data() throws Exception {
+ service.getCoveredConditionsData(COMPONENT_KEY);
+ verify(measureDataDao).findByComponentKeyAndMetricKey(COMPONENT_KEY, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
+ }
+
+}
--- /dev/null
+/*
+ * 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.test.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.server.test.CoverageService;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CoverageShowActionTest {
+
+ @Mock
+ CoverageService coverageService;
+
+ WsTester tester;
+
+ @Before
+ public void setUp() throws Exception {
+ tester = new WsTester(new CoverageWs(new CoverageShowAction(coverageService)));
+ }
+
+ @Test
+ public void show_coverage() throws Exception {
+ String fileKey = "src/Foo.java";
+ when(coverageService.getHitsData(fileKey)).thenReturn("1=8;2=2;3=5;4=1;5=1");
+
+ WsTester.TestRequest request = tester.newGetRequest("api/coverage", "show").setParam("key", fileKey);
+
+ request.execute().assertJson(getClass(), "show_coverage.json");
+ }
+
+ @Test
+ public void show_coverage_with_from_and_to() throws Exception {
+ String fileKey = "src/Foo.java";
+ when(coverageService.getHitsData(fileKey)).thenReturn("1=8;2=2;3=5;4=1;5=1");
+
+ WsTester.TestRequest request = tester.newGetRequest("api/coverage", "show").setParam("key", fileKey).setParam("from", "3").setParam("to", "4");
+
+ request.execute().assertJson(getClass(), "show_coverage_with_from_and_to.json");
+ }
+
+}
--- /dev/null
+/*
+ * 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.test.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.test.CoverageService;
+import org.sonar.server.ws.WsTester;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class CoverageWsTest {
+
+ WebService.Controller controller;
+
+ @Before
+ public void setUp() throws Exception {
+ WsTester tester = new WsTester(new CoverageWs(new CoverageShowAction(mock(CoverageService.class))));
+ controller = tester.controller("api/coverage");
+ }
+
+ @Test
+ public void define_controller() throws Exception {
+ assertThat(controller).isNotNull();
+ assertThat(controller.description()).isNotEmpty();
+ assertThat(controller.since()).isEqualTo("4.4");
+ assertThat(controller.isInternal()).isFalse();
+ assertThat(controller.actions()).hasSize(1);
+ }
+
+ @Test
+ public void define_show_action() throws Exception {
+ WebService.Action action = controller.action("show");
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isFalse();
+ assertThat(action.handler()).isNotNull();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params()).hasSize(4);
+ }
+
+}
package org.sonar.server.user;
import com.google.common.collect.HashMultimap;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
import org.sonar.core.user.AuthorizationDao;
import javax.annotation.Nullable;
import static com.google.common.collect.Lists.newArrayList;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class MockUserSession extends UserSession {
+ private final AuthorizationDao authorizationDao;
+
+ private final ResourceDao resourceDao;
+
private MockUserSession() {
globalPermissions = Collections.emptyList();
projectKeyByPermission = HashMultimap.create();
+ authorizationDao = mock(AuthorizationDao.class);
+ resourceDao = mock(ResourceDao.class);
}
public static MockUserSession set() {
return this;
}
+ public MockUserSession addComponent(String componentKey, String projectKey) {
+ when(resourceDao.getRootProjectByComponentKey(componentKey)).thenReturn(new ResourceDto().setKey(projectKey));
+ return this;
+ }
+
@Override
AuthorizationDao authorizationDao() {
- return mock(AuthorizationDao.class);
+ return authorizationDao;
+ }
+
+ @Override
+ ResourceDao resourceDao() {
+ return resourceDao;
}
}
package org.sonar.server.user;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.web.UserRole;
import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
import org.sonar.core.user.AuthorizationDao;
import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+
+import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Locale;
import static org.mockito.Mockito.when;
public class UserSessionTest {
+
+ @org.junit.Rule
+ public ExpectedException thrown = ExpectedException.none();
+
@Test
public void getSession_get_anonymous_by_default() throws Exception {
UserSession.remove();
session.checkProjectPermission(UserRole.USER, "com.foo:Bar");
}
+ @Test
+ public void check_component_permission_ok() throws Exception {
+ AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
+ ResourceDao resourceDao = mock(ResourceDao.class);
+ UserSession session = new SpyUserSession("marius", authorizationDao, resourceDao).setUserId(1);
+
+ when(resourceDao.getRootProjectByComponentKey("com.foo:Bar:BarFile.xoo")).thenReturn(new ResourceDto().setKey("com.foo:Bar"));
+ when(authorizationDao.selectAuthorizedRootProjectsKeys(1, UserRole.USER)).thenReturn(newArrayList("com.foo:Bar"));
+
+ session.checkComponentPermission(UserRole.USER, "com.foo:Bar:BarFile.xoo");
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void check_component_permission_ko() throws Exception {
+ AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
+ ResourceDao resourceDao = mock(ResourceDao.class);
+ UserSession session = new SpyUserSession("marius", authorizationDao, resourceDao).setUserId(1);
+
+ when(resourceDao.getRootProjectByComponentKey("com.foo:Bar:BarFile.xoo")).thenReturn(new ResourceDto().setKey("com.foo:Bar2"));
+ when(authorizationDao.selectAuthorizedRootProjectsKeys(1, UserRole.USER)).thenReturn(newArrayList("com.foo:Bar"));
+
+ session.checkComponentPermission(UserRole.USER, "com.foo:Bar:BarFile.xoo");
+ }
+
+ @Test
+ public void check_component_permission_when_project_not_found() throws Exception {
+ thrown.expect(NotFoundException.class);
+ thrown.expectMessage("Component 'com.foo:Bar:BarFile.xoo' does not exist");
+
+ AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
+ ResourceDao resourceDao = mock(ResourceDao.class);
+ UserSession session = new SpyUserSession("marius", authorizationDao, resourceDao).setUserId(1);
+
+ when(resourceDao.getRootProjectByComponentKey("com.foo:Bar:BarFile.xoo")).thenReturn(null);
+
+ session.checkComponentPermission(UserRole.USER, "com.foo:Bar:BarFile.xoo");
+ }
+
static class SpyUserSession extends UserSession {
private AuthorizationDao authorizationDao;
+ private ResourceDao resourceDao;
SpyUserSession(String login, AuthorizationDao authorizationDao) {
+ this(login, authorizationDao, null);
+ }
+
+ SpyUserSession(String login, AuthorizationDao authorizationDao, @Nullable ResourceDao resourceDao) {
this.authorizationDao = authorizationDao;
+ this.resourceDao = resourceDao;
setLogin(login);
}
AuthorizationDao authorizationDao() {
return authorizationDao;
}
+
+ @Override
+ ResourceDao resourceDao() {
+ return resourceDao;
+ }
+
}
}
--- /dev/null
+{
+ "coverage": [
+ [1, 8],
+ [2, 2],
+ [3, 5],
+ [4, 1],
+ [5, 1]
+ ]
+}
--- /dev/null
+{
+ "coverage": [
+ [3, 5],
+ [4, 1]
+ ]
+}