diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-08-24 15:44:24 +0200 |
---|---|---|
committer | Janos Gyerik <janos.gyerik@sonarsource.com> | 2017-09-12 11:34:51 +0200 |
commit | 84fb7ffe3889723aa29df14ebaf874f577aa2842 (patch) | |
tree | 39e2cd8d236fdc78b8b1be2f6f36ee66c4aa5bea | |
parent | 6997a3ff9b348ca9147ebe83ef33bc8b008a97a1 (diff) | |
download | sonarqube-84fb7ffe3889723aa29df14ebaf874f577aa2842.tar.gz sonarqube-84fb7ffe3889723aa29df14ebaf874f577aa2842.zip |
SONAR-9616 Handle branch in api/tests/list
4 files changed, 167 insertions, 132 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java index c323b1c1b5a..4d74a46d916 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java @@ -48,7 +48,11 @@ import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.Common; import org.sonarqube.ws.WsTests; +import static org.sonar.api.server.ws.WebService.Param.PAGE; +import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; +import static org.sonar.api.web.UserRole.*; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; +import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; public class ListAction implements TestsWsAction { @@ -58,6 +62,7 @@ public class ListAction implements TestsWsAction { public static final String SOURCE_FILE_ID = "sourceFileId"; public static final String SOURCE_FILE_KEY = "sourceFileKey"; public static final String SOURCE_FILE_LINE_NUMBER = "sourceFileLineNumber"; + public static final String PARAM_BRANCH = "branch"; private final DbClient dbClient; private final TestIndex testIndex; @@ -123,6 +128,12 @@ public class ListAction implements TestsWsAction { .createParam(SOURCE_FILE_LINE_NUMBER) .setDescription("Source file line number. Must be provided with the source file ID or key.") .setExampleValue("10"); + + action.createParam(PARAM_BRANCH) + .setDescription("Branch key") + .setSince("6.6") + .setInternal(true) + .setExampleValue(KEY_BRANCH_EXAMPLE_001); } @Override @@ -132,15 +143,16 @@ public class ListAction implements TestsWsAction { String testFileKey = request.param(TEST_FILE_KEY); String sourceFileUuid = request.param(SOURCE_FILE_ID); String sourceFileKey = request.param(SOURCE_FILE_KEY); + String branch = request.param(PARAM_BRANCH); Integer sourceFileLineNumber = request.paramAsInt(SOURCE_FILE_LINE_NUMBER); SearchOptions searchOptions = new SearchOptions().setPage( - request.mandatoryParamAsInt(WebService.Param.PAGE), - request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE)); + request.mandatoryParamAsInt(PAGE), + request.mandatoryParamAsInt(PAGE_SIZE)); SearchResult<TestDoc> tests; Map<String, ComponentDto> componentsByTestFileUuid; try (DbSession dbSession = dbClient.openSession(false)) { - tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileKey, sourceFileLineNumber, searchOptions); + tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileKey, branch, sourceFileLineNumber, searchOptions); componentsByTestFileUuid = buildComponentsByTestFileUuid(dbSession, tests.getDocs()); } @@ -194,22 +206,30 @@ public class ListAction implements TestsWsAction { } private SearchResult<TestDoc> searchTests(DbSession dbSession, @Nullable String testUuid, @Nullable String testFileUuid, @Nullable String testFileKey, - @Nullable String sourceFileUuid, @Nullable String sourceFileKey, @Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) { + @Nullable String sourceFileUuid, @Nullable String sourceFileKey, @Nullable String branch, @Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) { if (testUuid != null) { - return searchTestsByTestUuid(dbSession, testUuid, searchOptions); + TestDoc testDoc = checkFoundWithOptional(testIndex.getNullableByTestUuid(testUuid), "Test with id '%s' is not found", testUuid); + checkComponentUuidPermission(dbSession, testDoc.fileUuid()); + return testIndex.searchByTestUuid(testUuid, searchOptions); } if (testFileUuid != null) { - return searchTestsByTestFileUuid(dbSession, testFileUuid, searchOptions); + checkComponentUuidPermission(dbSession, testFileUuid); + return testIndex.searchByTestFileUuid(testFileUuid, searchOptions); } if (testFileKey != null) { - return searchTestsByTestFileKey(dbSession, testFileKey, searchOptions); + ComponentDto testFile = componentFinder.getByKeyAndOptionalBranch(dbSession, testFileKey, branch); + userSession.checkComponentPermission(CODEVIEWER, testFile); + return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions); } if (sourceFileUuid != null && sourceFileLineNumber != null) { - return searchTestsBySourceFileUuidAndLineNumber(dbSession, sourceFileUuid, sourceFileLineNumber, searchOptions); + ComponentDto sourceFile = componentFinder.getByUuid(dbSession, sourceFileUuid); + userSession.checkComponentPermission(CODEVIEWER, sourceFile); + return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions); } if (sourceFileKey != null && sourceFileLineNumber != null) { - ComponentDto component = componentFinder.getByKey(dbSession, sourceFileKey); - return searchTestsBySourceFileUuidAndLineNumber(dbSession, component.uuid(), sourceFileLineNumber, searchOptions); + ComponentDto sourceFile = componentFinder.getByKeyAndOptionalBranch(dbSession, sourceFileKey, branch); + userSession.checkComponentPermission(CODEVIEWER, sourceFile); + return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions); } throw new IllegalArgumentException( @@ -217,31 +237,9 @@ public class ListAction implements TestsWsAction { "3) test file key. 4) source file ID or key with a source file line number."); } - private SearchResult<TestDoc> searchTestsBySourceFileUuidAndLineNumber(DbSession dbSession, String sourceFileUuid, Integer sourceFileLineNumber, SearchOptions searchOptions) { - checkComponentUuidPermission(dbSession, sourceFileUuid); - return testIndex.searchBySourceFileUuidAndLineNumber(sourceFileUuid, sourceFileLineNumber, searchOptions); - } - - private SearchResult<TestDoc> searchTestsByTestFileKey(DbSession dbSession, String testFileKey, SearchOptions searchOptions) { - ComponentDto testFile = componentFinder.getByKey(dbSession, testFileKey); - userSession.checkComponentPermission(UserRole.CODEVIEWER, testFile); - return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions); - } - - private SearchResult<TestDoc> searchTestsByTestFileUuid(DbSession dbSession, String testFileUuid, SearchOptions searchOptions) { - checkComponentUuidPermission(dbSession, testFileUuid); - return testIndex.searchByTestFileUuid(testFileUuid, searchOptions); - } - - private SearchResult<TestDoc> searchTestsByTestUuid(DbSession dbSession, String testUuid, SearchOptions searchOptions) { - TestDoc testDoc = checkFoundWithOptional(testIndex.getNullableByTestUuid(testUuid), "Test with id '%s' is not found", testUuid); - checkComponentUuidPermission(dbSession, testDoc.fileUuid()); - return testIndex.searchByTestUuid(testUuid, searchOptions); - } - private void checkComponentUuidPermission(DbSession dbSession, String componentUuid) { ComponentDto component = componentFinder.getByUuid(dbSession, componentUuid); - userSession.checkComponentPermission(UserRole.CODEVIEWER, component); + userSession.checkComponentPermission(CODEVIEWER, component); } private static class TestToFileUuidFunction implements Function<TestDoc, String> { diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java index 398e77f6e02..0822dd9a19a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.server.ws.WebService; import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -40,6 +41,7 @@ import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyString; @@ -73,6 +75,17 @@ public class CoveredFilesActionTest { } @Test + public void define_covered_files() { + WebService.Action action = ws.getDef(); + assertThat(action).isNotNull(); + assertThat(action.isInternal()).isFalse(); + assertThat(action.isPost()).isFalse(); + assertThat(action.handler()).isNotNull(); + assertThat(action.responseExampleAsString()).isNotEmpty(); + assertThat(action.params()).hasSize(3); + } + + @Test public void covered_files() { ComponentDto project = ComponentTesting.newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), "SonarQube"); ComponentDto file = ComponentTesting.newFileDto(project, null, "test-file-uuid"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java index 7c804bdf59a..f38ce3efc24 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java @@ -24,6 +24,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -43,6 +44,7 @@ import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.WsTests; import org.sonarqube.ws.WsTests.ListResponse; +import static java.lang.String.format; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; @@ -88,6 +90,27 @@ public class ListActionTest { } @Test + public void test_definition() { + WebService.Action action = ws.getDef(); + assertThat(action).isNotNull(); + assertThat(action.isInternal()).isFalse(); + assertThat(action.isPost()).isFalse(); + assertThat(action.handler()).isNotNull(); + assertThat(action.responseExampleAsString()).isNotEmpty(); + assertThat(action.params()).hasSize(9); + assertThat(action.description()).isEqualTo("Get the list of tests either in a test file or that test a given line of source code.<br /> " + + "Require Browse permission on the file's project.<br /> " + + "One (and only one) of the following combination of parameters must be provided: " + + "<ul>" + + "<li>testId - get a specific test</li>" + + "<li>testFileId - get the tests in a test file</li>" + + "<li>testFileKey - get the tests in a test file</li>" + + "<li>sourceFileId and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + + "<li>sourceFileKey and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + + "</ul>"); + } + + @Test public void list_tests() throws Exception { userSessionRule.addProjectPermission(CODEVIEWER, project); DbFileSources.Test test = newTest(mainFile, 10, 11, 12, 20, 21, 25).setStatus(OK).build(); @@ -116,9 +139,12 @@ public class ListActionTest { DbFileSources.Test test2 = newTest(mainFile, 11).build(); insertTests(testFile, test1, test2); - ListResponse request = call(ws.newRequest().setParam(TEST_ID, test1.getUuid())); + ListResponse request = call(ws.newRequest() + .setParam(TEST_ID, test1.getUuid())); - assertThat(request.getTestsList()).extracting(WsTests.Test::getId).containsOnly(test1.getUuid()); + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid()); } @Test @@ -131,9 +157,12 @@ public class ListActionTest { insertTests(testFile, test1, test2); insertTests(anotherTestFile, test3); - ListResponse request = call(ws.newRequest().setParam(TEST_FILE_ID, testFile.uuid())); + ListResponse request = call(ws.newRequest() + .setParam(TEST_FILE_ID, testFile.uuid())); - assertThat(request.getTestsList()).extracting(WsTests.Test::getId).containsOnly(test1.getUuid(), test2.getUuid()); + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid(), test2.getUuid()); } @Test @@ -146,9 +175,33 @@ public class ListActionTest { insertTests(testFile, test1, test2); insertTests(anotherTestFile, test3); - ListResponse request = call(ws.newRequest().setParam(TEST_FILE_KEY, testFile.getDbKey())); + ListResponse request = call(ws.newRequest() + .setParam(TEST_FILE_KEY, testFile.getDbKey())); - assertThat(request.getTestsList()).extracting(WsTests.Test::getId).containsOnly(test1.getUuid(), test2.getUuid()); + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid(), test2.getUuid()); + } + + @Test + public void list_tests_by_test_file_key_and_branch() throws Exception { + ComponentDto project = db.components().insertMainBranch(); + userSessionRule.addProjectPermission(CODEVIEWER, project); + ComponentDto branch = db.components().insertProjectBranch(project); + ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); + ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); + + DbFileSources.Test test1 = newTest(mainFile, 10).build(); + DbFileSources.Test test2 = newTest(mainFile, 11).build(); + insertTests(testFile, test1, test2); + + ListResponse request = call(ws.newRequest() + .setParam(TEST_FILE_KEY, testFile.getKey()) + .setParam("branch", testFile.getBranch())); + + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid(), test2.getUuid()); } @Test @@ -161,7 +214,9 @@ public class ListActionTest { DbFileSources.Test test4 = newTest(anotherMainFile, 11).build(); insertTests(testFile, test1, test2, test3, test4); - ListResponse request = call(ws.newRequest().setParam(SOURCE_FILE_ID, mainFile.uuid()).setParam(SOURCE_FILE_LINE_NUMBER, "11")); + ListResponse request = call(ws.newRequest() + .setParam(SOURCE_FILE_ID, mainFile.uuid()) + .setParam(SOURCE_FILE_LINE_NUMBER, "11")); assertThat(request.getTestsList()).extracting(WsTests.Test::getId).containsOnly(test1.getUuid(), test2.getUuid()); } @@ -176,9 +231,35 @@ public class ListActionTest { DbFileSources.Test test4 = newTest(anotherMainFile, 11).build(); insertTests(testFile, test1, test2, test3, test4); - ListResponse request = call(ws.newRequest().setParam(SOURCE_FILE_KEY, mainFile.getDbKey()).setParam(SOURCE_FILE_LINE_NUMBER, "10")); + ListResponse request = call(ws.newRequest() + .setParam(SOURCE_FILE_KEY, mainFile.getDbKey()) + .setParam(SOURCE_FILE_LINE_NUMBER, "10")); + + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid(), test3.getUuid()); + } + + @Test + public void list_tests_by_source_file_key_and_branch_and_line_number() throws Exception { + ComponentDto project = db.components().insertMainBranch(); + userSessionRule.addProjectPermission(CODEVIEWER, project); + ComponentDto branch = db.components().insertProjectBranch(project); + ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); + ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); + DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build(); + DbFileSources.Test test2 = newTest(mainFile, 9, 11).build(); + DbFileSources.Test test3 = newTest(mainFile, 10, 12).build(); + insertTests(testFile, test1, test2, test3); + + ListResponse request = call(ws.newRequest() + .setParam(SOURCE_FILE_KEY, mainFile.getKey()) + .setParam(SOURCE_FILE_LINE_NUMBER, "10") + .setParam("branch", testFile.getBranch())); - assertThat(request.getTestsList()).extracting(WsTests.Test::getId).containsOnly(test1.getUuid(), test3.getUuid()); + assertThat(request.getTestsList()) + .extracting(WsTests.Test::getId) + .containsOnly(test1.getUuid(), test3.getUuid()); } @Test @@ -261,7 +342,22 @@ public class ListActionTest { @Test public void fail_when_test_file_key_is_unknown() throws Exception { expectedException.expect(NotFoundException.class); - call(ws.newRequest().setParam(TEST_FILE_ID, "unknown")); + call(ws.newRequest().setParam(TEST_FILE_KEY, "unknown")); + } + + @Test + public void fail_when_test_branch_is_unknown() throws Exception { + ComponentDto project = db.components().insertMainBranch(); + userSessionRule.addProjectPermission(CODEVIEWER, project); + ComponentDto branch = db.components().insertProjectBranch(project); + ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", testFile.getKey())); + + call(ws.newRequest() + .setParam(TEST_FILE_KEY, testFile.getKey()) + .setParam("branch", "unknown")); } @Test @@ -276,9 +372,25 @@ public class ListActionTest { call(ws.newRequest().setParam(SOURCE_FILE_KEY, "unknown").setParam(SOURCE_FILE_LINE_NUMBER, "10")); } + @Test + public void fail_when_source_branch_is_unknown() throws Exception { + ComponentDto project = db.components().insertMainBranch(); + userSessionRule.addProjectPermission(CODEVIEWER, project); + ComponentDto branch = db.components().insertProjectBranch(project); + ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", mainFile.getKey())); + + call(ws.newRequest() + .setParam(SOURCE_FILE_KEY, mainFile.getKey()) + .setParam("branch", "unknown") + .setParam(SOURCE_FILE_LINE_NUMBER, "10")); + } + private void insertTests(ComponentDto testFile, DbFileSources.Test... tests) { db.getDbClient().fileSourceDao().insert(db.getSession(), new FileSourceDto() - .setProjectUuid(project.uuid()) + .setProjectUuid(testFile.projectUuid()) .setFileUuid(testFile.uuid()) .setTestData(asList(tests))); db.commit(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsWsTest.java deleted file mode 100644 index a0cd8233c70..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/test/ws/TestsWsTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.Rule; -import org.junit.Test; -import org.sonar.api.server.ws.WebService; -import org.sonar.db.DbClient; -import org.sonar.server.component.ComponentFinder; -import org.sonar.server.test.index.TestIndex; -import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.ws.WsTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -public class TestsWsTest { - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - - WebService.Controller controller; - - @Before - public void setUp() { - WsTester tester = new WsTester(new TestsWs( - new ListAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule, mock(ComponentFinder.class)), - new CoveredFilesAction(mock(DbClient.class), mock(TestIndex.class), userSessionRule))); - controller = tester.controller("api/tests"); - } - - @Test - public void define_controller() { - assertThat(controller).isNotNull(); - assertThat(controller.since()).isEqualTo("4.4"); - assertThat(controller.description()).isNotEmpty(); - assertThat(controller.actions()).hasSize(2); - } - - @Test - public void define_list_action() { - WebService.Action action = controller.action("list"); - assertThat(action).isNotNull(); - assertThat(action.isInternal()).isFalse(); - assertThat(action.isPost()).isFalse(); - assertThat(action.handler()).isNotNull(); - assertThat(action.responseExampleAsString()).isNotEmpty(); - assertThat(action.params()).hasSize(8); - assertThat(action.description()).isEqualTo("Get the list of tests either in a test file or that test a given line of source code.<br /> " + - "Require Browse permission on the file's project.<br /> " + - "One (and only one) of the following combination of parameters must be provided: " + - "<ul>" + - "<li>testId - get a specific test</li>" + - "<li>testFileId - get the tests in a test file</li>" + - "<li>testFileKey - get the tests in a test file</li>" + - "<li>sourceFileId and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + - "<li>sourceFileKey and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + - "</ul>"); - } - - @Test - public void define_covered_files() { - WebService.Action action = controller.action("covered_files"); - assertThat(action).isNotNull(); - assertThat(action.isInternal()).isFalse(); - assertThat(action.isPost()).isFalse(); - assertThat(action.handler()).isNotNull(); - assertThat(action.responseExampleAsString()).isNotEmpty(); - assertThat(action.params()).hasSize(3); - } -} |