Browse Source

SONAR-5286 Provide a new "/api/duplications/show" WS

tags/4.4-RC1
Julien Lancelot 10 years ago
parent
commit
66089b3530

+ 8
- 4
sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java View File

@@ -21,11 +21,11 @@ package org.sonar.server.component.persistence;

import com.google.common.annotations.VisibleForTesting;
import org.apache.ibatis.session.SqlSession;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.System2;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.db.ComponentMapper;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.BaseDao;

@@ -62,21 +62,25 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String>

@Override
protected ComponentDto doInsert(ComponentDto item, DbSession session) {
throw new IllegalStateException("Not implemented yet");
throw notImplemented();
}

@Override
protected ComponentDto doUpdate(ComponentDto item, DbSession session) {
throw new IllegalStateException("Not implemented yet");
throw notImplemented();
}

@Override
protected void doDeleteByKey(String key, DbSession session) {
throw new IllegalStateException("Not implemented yet");
throw notImplemented();
}

@Override
public Iterable<String> keysOfRowsUpdatedAfter(long timestamp, DbSession session) {
throw notImplemented();
}

private static IllegalStateException notImplemented() {
throw new IllegalStateException("Not implemented yet");
}
}

+ 129
- 0
sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsWriter.java View File

@@ -0,0 +1,129 @@
/*
* 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.duplication.ws;

import com.google.common.annotations.VisibleForTesting;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.component.persistence.ComponentDao;

import javax.annotation.Nullable;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;

import java.io.StringReader;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

public class DuplicationsWriter implements ServerComponent {

private final ComponentDao componentDao;

public DuplicationsWriter(ComponentDao componentDao) {
this.componentDao = componentDao;
}

@VisibleForTesting
void write(@Nullable String duplicationsData, JsonWriter json, DbSession session) {
Map<String, String> refByComponentKey = newHashMap();
json.name("duplications").beginArray();
if (duplicationsData != null) {
writeDuplications(duplicationsData, refByComponentKey, json, session);
}
json.endArray();

json.name("files").beginObject();
writeFiles(refByComponentKey, json, session);
json.endObject();
}

private void writeDuplications(String duplicationsData, Map<String, String> refByComponentKey, JsonWriter json, DbSession session) {
try {
SMInputFactory inputFactory = initStax();
SMHierarchicCursor root = inputFactory.rootElementCursor(new StringReader(duplicationsData));
root.advance(); // <duplications>
SMInputCursor cursor = root.childElementCursor("g");
while (cursor.getNext() != null) {
json.beginObject().name("blocks").beginArray();
SMInputCursor bCursor = cursor.childElementCursor("b");
while (bCursor.getNext() != null) {
String from = bCursor.getAttrValue("s");
String size = bCursor.getAttrValue("l");
String componentKey = bCursor.getAttrValue("r");
if (from != null && size != null && componentKey != null) {
String ref = refByComponentKey.get(componentKey);
if (ref == null) {
ref = Integer.toString(refByComponentKey.size() + 1);
refByComponentKey.put(componentKey, Integer.toString(refByComponentKey.size() + 1));
}

json.beginObject();
json.prop("from", Integer.valueOf(from));
json.prop("size", Integer.valueOf(size));
json.prop("_ref", ref);
json.endObject();
}
}
json.endArray().endObject();
}
} catch (XMLStreamException e) {
throw new IllegalStateException("XML is not valid", e);
}
}

private void writeFiles(Map<String, String> refByComponentKey, JsonWriter json, DbSession session) {
Map<Long, ComponentDto> projectById = newHashMap();
for (Map.Entry<String, String> entry : refByComponentKey.entrySet()) {
String componentKey = entry.getKey();
String ref = entry.getValue();
ComponentDto file = componentDao.getByKey(componentKey, session);
if (file != null) {
json.name(ref).beginObject();
json.prop("key", file.key());
json.prop("name", file.longName());
ComponentDto project = projectById.get(file.projectId());
if (project == null) {
project = componentDao.getById(file.projectId(), session);
projectById.put(file.projectId(), project);
}
json.prop("projectName", project != null ? project.longName() : null);
json.endObject();
}
}
}

private static SMInputFactory initStax() {
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
// just so it won't try to load DTD in if there's DOCTYPE
xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
return new SMInputFactory(xmlFactory);
}

}

+ 41
- 0
sonar-server/src/main/java/org/sonar/server/duplication/ws/DuplicationsWs.java View File

@@ -0,0 +1,41 @@
/*
* 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.duplication.ws;

import org.sonar.api.server.ws.WebService;

public class DuplicationsWs implements WebService {

private final ShowAction showAction;

public DuplicationsWs(ShowAction showAction) {
this.showAction = showAction;
}

@Override
public void define(Context context) {
NewController controller = context.createController("api/duplications")
.setSince("4.4")
.setDescription("Display duplications information");
showAction.define(controller);
controller.done();
}
}

+ 91
- 0
sonar-server/src/main/java/org/sonar/server/duplication/ws/ShowAction.java View File

@@ -0,0 +1,91 @@
/*
* 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.duplication.ws;

import com.google.common.io.Resources;
import org.sonar.api.measures.CoreMetrics;
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.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.measure.db.MeasureDto;
import org.sonar.core.measure.db.MeasureKey;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.db.DbClient;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.user.UserSession;

import javax.annotation.CheckForNull;

public class ShowAction implements RequestHandler {

private final DbClient dbClient;
private final MeasureDao measureDao;
private final DuplicationsWriter duplicationsWriter;

public ShowAction(DbClient dbClient, MeasureDao measureDao, DuplicationsWriter duplicationsWriter) {
this.dbClient = dbClient;
this.measureDao = measureDao;
this.duplicationsWriter = duplicationsWriter;
}

void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("show")
.setDescription("Get duplications. Require Browse permission on file's project")
.setSince("4.4")
.setHandler(this)
.setResponseExample(Resources.getResource(this.getClass(), "example-show.json"));

action
.createParam("key")
.setRequired(true)
.setDescription("File key")
.setExampleValue("my_project:/src/foo/Bar.php");
}

@Override
public void handle(Request request, Response response) {
String fileKey = request.mandatoryParam("key");
UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);

DbSession session = dbClient.openSession(false);
try {
JsonWriter json = response.newJsonWriter().beginObject();
String duplications = findDataFromComponent(fileKey, CoreMetrics.DUPLICATIONS_DATA_KEY, session);
duplicationsWriter.write(duplications, json, session);
json.endObject().close();
} finally {
MyBatis.closeQuietly(session);
}
}

@CheckForNull
private String findDataFromComponent(String fileKey, String metricKey, DbSession session) {
MeasureDto data = measureDao.getByKey(MeasureKey.of(fileKey, metricKey), session);
if (data != null) {
return data.getData();
}
return null;
}
}

+ 24
- 0
sonar-server/src/main/java/org/sonar/server/duplication/ws/package-info.java View File

@@ -0,0 +1,24 @@
/*
* 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.
*/

@ParametersAreNonnullByDefault
package org.sonar.server.duplication.ws;

import javax.annotation.ParametersAreNonnullByDefault;

+ 19
- 115
sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java View File

@@ -52,13 +52,7 @@ import org.sonar.core.measure.db.MeasureFilterDao;
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;
@@ -94,32 +88,12 @@ import org.sonar.server.db.DbClient;
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.duplication.ws.DuplicationsWriter;
import org.sonar.server.duplication.ws.DuplicationsWs;
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;
@@ -141,74 +115,23 @@ import org.sonar.server.permission.ws.PermissionsWs;
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.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.QProfiles;
import org.sonar.server.qualityprofile.QualityProfileService;
import org.sonar.server.qualityprofile.RegisterQualityProfiles;
import org.sonar.server.qualityprofile.RuleActivationContextFactory;
import org.sonar.server.qualitygate.ws.*;
import org.sonar.server.qualityprofile.*;
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.BulkRuleActivationActions;
import org.sonar.server.qualityprofile.ws.ProfilesWs;
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.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.Rules;
import org.sonar.server.qualityprofile.ws.*;
import org.sonar.server.rule.*;
import org.sonar.server.rule2.RegisterRules;
import org.sonar.server.rule2.RuleService;
import org.sonar.server.rule2.index.RuleIndex;
import org.sonar.server.rule2.index.RuleNormalizer;
import org.sonar.server.rule2.persistence.RuleDao;
import org.sonar.server.rule2.ws.RuleMapping;
import org.sonar.server.rule2.ws.RulesWebService;
import org.sonar.server.rule2.ws.SearchAction;
import org.sonar.server.rule2.ws.SetNoteAction;
import org.sonar.server.rule2.ws.SetTagsAction;
import org.sonar.server.rule2.ws.TagsAction;
import org.sonar.server.rule2.ws.*;
import org.sonar.server.search.IndexClient;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.source.DeprecatedSourceDecorator;
@@ -218,20 +141,7 @@ import org.sonar.server.source.ws.ScmAction;
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;
@@ -243,20 +153,9 @@ import org.sonar.server.ui.JRubyProfiling;
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;

@@ -566,6 +465,11 @@ class ServerComponents {
pico.addSingleton(ScmWriter.class);
pico.addSingleton(ScmAction.class);

// Duplications
pico.addSingleton(DuplicationsWs.class);
pico.addSingleton(DuplicationsWriter.class);
pico.addSingleton(org.sonar.server.duplication.ws.ShowAction.class);

// text
pico.addSingleton(MacroInterpreter.class);
pico.addSingleton(RubyTextService.class);

+ 54
- 0
sonar-server/src/main/resources/org/sonar/server/duplication/ws/example-show.json View File

@@ -0,0 +1,54 @@
{
"duplications": [
{
"blocks": [
{
"from": 94, "size": 101, "_ref": "1"
},
{
"from": 83, "size": 101, "_ref": "2"
}
]
},
{
"blocks": [
{
"from": 38, "size": 40, "_ref": "1"
},
{
"from": 29, "size": 39, "_ref": "2"
}
]
},
{
"blocks": [
{
"from": 148, "size": 24, "_ref": "1"
},
{
"from": 137, "size": 24, "_ref": "2"
},
{
"from": 137, "size": 24, "_ref": "3"
}
]
}
],
"files": {
"1": {
"key": "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/utils/command/CommandExecutor.java",
"name": "CommandExecutor",
"projectName": "SonarQube"
},
"2": {
"key": "com.sonarsource.orchestrator:sonar-orchestrator:src/main/java/com/sonar/orchestrator/util/CommandExecutor.java",
"name": "CommandExecutor",
"projectName": "SonarSource :: Orchestrator"
},
"3": {
"key": "org.codehaus.sonar.runner:sonar-runner-api:src/main/java/org/sonar/runner/api/CommandExecutor.java",
"name": "CommandExecutor",
"projectName": "SonarSource Runner"
}
}
}

+ 124
- 0
sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsWriterTest.java View File

@@ -0,0 +1,124 @@
/*
* 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.duplication.ws;

import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.skyscreamer.jsonassert.JSONAssert;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.component.persistence.ComponentDao;

import javax.annotation.Nullable;

import java.io.StringWriter;

import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DuplicationsWriterTest {

@Mock
ComponentDao componentDao;

@Mock
DbSession session;

DuplicationsWriter writer;

@Before
public void setUp() throws Exception {
writer = new DuplicationsWriter(componentDao);
}

@Test
public void write_duplications() throws Exception {
String key1 = "org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java";
ComponentDto file1 = new ComponentDto().setId(10L).setQualifier("FIL").setKey(key1).setLongName("PropertyDeleteQuery").setProjectId(1L);
String key2 = "org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java";
ComponentDto file2 = new ComponentDto().setId(11L).setQualifier("FIL").setKey(key2).setLongName("PropertyUpdateQuery").setProjectId(1L);

when(componentDao.getByKey(key1, session)).thenReturn(file1);
when(componentDao.getByKey(key2, session)).thenReturn(file2);
when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setLongName("SonarQube"));

test(
"<duplications>\n" +
"<g>\n" +
"<b s=\"57\" l=\"12\" r=\"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java\"/>\n" +
"<b s=\"73\" l=\"12\" r=\"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java\"/>\n" +
"</g>\n" +
"</duplications>",
"{\n" +
" \"duplications\": [\n" +
" {\n" +
" \"blocks\": [\n" +
" {\n" +
" \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
" },\n" +
" {\n" +
" \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" +
" }\n" +
" ]\n" +
" }," +
" ],\n" +
" \"files\": {\n" +
" \"1\": {\n" +
" \"key\": \"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyDeleteQuery.java\",\n" +
" \"name\": \"PropertyDeleteQuery\",\n" +
" \"projectName\": \"SonarQube\"\n" +
" },\n" +
" \"2\": {\n" +
" \"key\": \"org.codehaus.sonar:sonar-ws-client:src/main/java/org/sonar/wsclient/services/PropertyUpdateQuery.java\",\n" +
" \"name\": \"PropertyUpdateQuery\",\n" +
" \"projectName\": \"SonarQube\"\n" +
" }\n" +
" }" +
"}"
);

verify(componentDao, times(2)).getByKey(anyString(), eq(session));
verify(componentDao, times(1)).getById(anyLong(), eq(session));
}

@Test
public void write_nothing_when_no_data() throws Exception {
test(null, "{\"duplications\": [], \"files\": {}}");
}

private void test(@Nullable String duplications, String expected) throws JSONException {
StringWriter output = new StringWriter();
JsonWriter jsonWriter = JsonWriter.of(output);
jsonWriter.beginObject();
writer.write(duplications, jsonWriter, session);
jsonWriter.endObject();
JSONAssert.assertEquals(output.toString(), expected, true);
}

}

+ 52
- 0
sonar-server/src/test/java/org/sonar/server/duplication/ws/DuplicationsWsTest.java View File

@@ -0,0 +1,52 @@
/*
* 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.duplication.ws;

import org.junit.Test;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.db.DbClient;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.ws.WsTester;

import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class DuplicationsWsTest {

WsTester tester = new WsTester(new DuplicationsWs(new ShowAction(mock(DbClient.class), mock(MeasureDao.class), mock(DuplicationsWriter.class))));

@Test
public void define_ws() throws Exception {
WebService.Controller controller = tester.controller("api/duplications");
assertThat(controller).isNotNull();
assertThat(controller.since()).isEqualTo("4.4");
assertThat(controller.description()).isNotEmpty();

WebService.Action show = controller.action("show");
assertThat(show).isNotNull();
assertThat(show.handler()).isNotNull();
assertThat(show.since()).isEqualTo("4.4");
assertThat(show.isInternal()).isFalse();
assertThat(show.responseExampleAsString()).isNotEmpty();
assertThat(show.params()).hasSize(1);
}

}

+ 96
- 0
sonar-server/src/test/java/org/sonar/server/duplication/ws/ShowActionTest.java View File

@@ -0,0 +1,96 @@
/*
* 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.duplication.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.api.measures.CoreMetrics;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.measure.db.MeasureDto;
import org.sonar.core.measure.db.MeasureKey;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ShowActionTest {

@Mock
DbSession session;

@Mock
DbClient dbClient;

@Mock
MeasureDao measureDao;

@Mock
DuplicationsWriter duplicationsWriter;

WsTester tester;

@Before
public void setUp() throws Exception {
when(dbClient.openSession(false)).thenReturn(session);
tester = new WsTester(new DuplicationsWs(new ShowAction(dbClient, measureDao, duplicationsWriter)));
}

@Test
public void show_duplications() throws Exception {
String componentKey = "src/Foo.java";
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "org.codehaus.sonar:sonar", componentKey);

MeasureKey measureKey = MeasureKey.of(componentKey, CoreMetrics.DUPLICATIONS_DATA_KEY);
when(measureDao.getByKey(measureKey, session)).thenReturn(
MeasureDto.createFor(measureKey).setTextValue("{duplications}")
);

WsTester.TestRequest request = tester.newGetRequest("api/duplications", "show").setParam("key", componentKey);
request.execute();

verify(duplicationsWriter).write(eq("{duplications}"), any(JsonWriter.class), eq(session));
}

@Test
public void no_duplications_when_no_data() throws Exception {
String componentKey = "src/Foo.java";
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "org.codehaus.sonar:sonar", componentKey);

MeasureKey measureKey = MeasureKey.of(componentKey, CoreMetrics.DUPLICATIONS_DATA_KEY);
when(measureDao.getByKey(measureKey, session)).thenReturn(null);

WsTester.TestRequest request = tester.newGetRequest("api/duplications", "show").setParam("key", componentKey);
request.execute();

verify(duplicationsWriter).write(isNull(String.class), any(JsonWriter.class), eq(session));
}

}

Loading…
Cancel
Save