diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java index 14e8636561c8..52cfdb646aec 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java @@ -29,9 +29,12 @@ import org.sonar.core.util.Uuids; import org.sonar.db.Dao; import org.sonar.db.DbSession; +import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.KeyType; import static java.util.Collections.singletonList; +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.db.DatabaseUtils.executeLargeInputs; public class LiveMeasureDao implements Dao { @@ -78,6 +81,17 @@ public void selectTreeByQuery(DbSession dbSession, ComponentDto baseComponent, M mapper(dbSession).selectTreeByQuery(query, baseComponent.uuid(), query.getUuidPath(baseComponent), resultHandler); } + /** + * Example: + * If Main Branch = 0 LOCs (provisioned but never analyzed) and the "largest long-lived branch" is 120 LOCs, I'm expecting to consider the value 120. + * If Main Branch = 100 LOCs and the "largest long-lived branch" is 120 LOCs, I'm expecting to consider the value 120. + * If Main Branch = 100 LOCs and the "largest long-lived branch" is 80 LOCs, I'm expecting to consider the value 100. + */ + public long sumNclocOfBiggestLongLivingBranch(DbSession dbSession) { + Long ncloc = mapper(dbSession).sumNclocOfBiggestLongLivingBranch(NCLOC_KEY, KeyType.BRANCH, BranchType.LONG); + return ncloc == null ? 0L : ncloc; + } + public void insert(DbSession dbSession, LiveMeasureDto dto) { mapper(dbSession).insert(dto, Uuids.create(), null, system2.now()); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java index b6a115470dc5..c0fca2f6a1ea 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureMapper.java @@ -24,6 +24,8 @@ import javax.annotation.Nullable; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.session.ResultHandler; +import org.sonar.db.component.BranchType; +import org.sonar.db.component.KeyType; public interface LiveMeasureMapper { @@ -41,6 +43,11 @@ void selectTreeByQuery( @Param("baseUuidPath") String baseUuidPath, ResultHandler resultHandler); + Long sumNclocOfBiggestLongLivingBranch( + @Param("ncloc") String nclocKey, + @Param("branch") KeyType branchOrPullRequest, + @Param("branchType") BranchType branchType); + void insert( @Param("dto") LiveMeasureDto dto, @Param("uuid") String uuid, diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml index 38c973317367..6b571f5dc713 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml @@ -34,6 +34,25 @@ + + insert into live_measures ( uuid, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java index a37fc2ce3b3f..ed1b1e10e0f7 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/LiveMeasureDaoTest.java @@ -27,8 +27,10 @@ import org.junit.Test; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; +import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; import org.sonar.db.metric.MetricDto; +import org.sonar.db.organization.OrganizationDto; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -36,6 +38,7 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; +import static org.sonar.api.measures.Metric.ValueType.INT; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; @@ -54,7 +57,7 @@ public void setUp() throws Exception { } @Test - public void test_selectByComponentUuidsAndMetricIds() { + public void selectByComponentUuidsAndMetricIds() { LiveMeasureDto measure1 = newLiveMeasure().setMetricId(metric.getId()); LiveMeasureDto measure2 = newLiveMeasure().setMetricId(metric.getId()); underTest.insert(db.getSession(), measure1); @@ -94,7 +97,7 @@ public void selectByComponentUuidsAndMetricIds_returns_empty_list_if_component_d } @Test - public void test_selectByComponentUuidsAndMetricKeys() { + public void selectByComponentUuidsAndMetricKeys() { LiveMeasureDto measure1 = newLiveMeasure().setMetricId(metric.getId()); LiveMeasureDto measure2 = newLiveMeasure().setMetricId(metric.getId()); underTest.insert(db.getSession(), measure1); @@ -133,7 +136,7 @@ public void selectByComponentUuidsAndMetricKeys_returns_empty_list_if_component_ } @Test - public void test_selectMeasure() { + public void selectMeasure() { MetricDto metric = db.measures().insertMetric(); LiveMeasureDto stored = newLiveMeasure().setMetricId(metric.getId()); underTest.insert(db.getSession(), stored); @@ -198,6 +201,39 @@ public void selectMeasure_map_fields() { .contains(project.uuid(), file.uuid(), metric.getId(), 3.14, 0.1, "text_value", "text_value"); } + @Test + public void countNcloc() { + OrganizationDto organization = db.organizations().insert(); + MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); + MetricDto lines = db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString())); + + ComponentDto simpleProject = db.components().insertMainBranch(organization); + db.measures().insertLiveMeasure(simpleProject, ncloc, m -> m.setValue(10d)); + + ComponentDto projectWithBiggerLongLivingBranch = db.components().insertMainBranch(organization); + ComponentDto bigLongLivingBranch = db.components().insertProjectBranch(projectWithBiggerLongLivingBranch, b -> b.setBranchType(BranchType.LONG)); + db.measures().insertLiveMeasure(projectWithBiggerLongLivingBranch, ncloc, m -> m.setValue(100d)); + db.measures().insertLiveMeasure(bigLongLivingBranch, ncloc, m -> m.setValue(200d)); + + ComponentDto projectWithLinesButNoLoc = db.components().insertMainBranch(organization); + db.measures().insertLiveMeasure(projectWithLinesButNoLoc, lines, m -> m.setValue(365d)); + db.measures().insertLiveMeasure(projectWithLinesButNoLoc, ncloc, m -> m.setValue(0d)); + + long result = underTest.sumNclocOfBiggestLongLivingBranch(db.getSession()); + + assertThat(result).isEqualTo(10L + 200L); + } + + @Test + public void countNcloc_empty() { + db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString())); + db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString())); + + long result = underTest.sumNclocOfBiggestLongLivingBranch(db.getSession()); + + assertThat(result).isEqualTo(0L); + } + @Test public void insert_data() { byte[] data = "text_value".getBytes(StandardCharsets.UTF_8); @@ -215,7 +251,7 @@ public void insert_data() { } @Test - public void test_insertOrUpdate() { + public void insertOrUpdate() { // insert LiveMeasureDto dto = newLiveMeasure(); underTest.insertOrUpdate(db.getSession(), dto, "foo"); diff --git a/tests/src/test/java/util/XooProjectBuilder.java b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/XooProjectBuilder.java similarity index 85% rename from tests/src/test/java/util/XooProjectBuilder.java rename to server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/XooProjectBuilder.java index c9e8c8265b8b..36deec644d6f 100644 --- a/tests/src/test/java/util/XooProjectBuilder.java +++ b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/XooProjectBuilder.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package util; +package org.sonarqube.qa.util; import java.io.File; import java.io.IOException; @@ -34,6 +34,7 @@ public class XooProjectBuilder { private final String key; private final List moduleKeys = new ArrayList<>(); private int filesPerModule = 1; + private Properties projectProperties = new Properties(); public XooProjectBuilder(String projectKey) { this.key = projectKey; @@ -50,13 +51,19 @@ public XooProjectBuilder setFilesPerModule(int i) { return this; } + public XooProjectBuilder addProjectProperties(String... keyValueProperties) { + for (int i = 0; i < keyValueProperties.length; i += 2) { + this.projectProperties.setProperty(keyValueProperties[i], keyValueProperties[i + 1]); + } + return this; + } + public File build(File dir) { for (String moduleKey : moduleKeys) { generateModule(moduleKey, new File(dir, moduleKey), new Properties()); } - Properties additionalProps = new Properties(); - additionalProps.setProperty("sonar.modules", StringUtils.join(moduleKeys, ",")); - generateModule(key, dir, additionalProps); + projectProperties.setProperty("sonar.modules", StringUtils.join(moduleKeys, ",")); + generateModule(key, dir, projectProperties); return dir; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/edition/ws/FormDataAction.java b/server/sonar-server/src/main/java/org/sonar/server/edition/ws/FormDataAction.java index ebb732e19803..601b5b9de883 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/edition/ws/FormDataAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/edition/ws/FormDataAction.java @@ -23,20 +23,22 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.server.measure.index.ProjectMeasuresIndex; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.server.user.UserSession; -import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.Editions.FormDataResponse; +import static org.sonar.server.ws.WsUtils.writeProtobuf; + public class FormDataAction implements EditionsWsAction { private final UserSession userSession; private final Server server; - private final ProjectMeasuresIndex measuresIndex; + private final DbClient dbClient; - public FormDataAction(UserSession userSession, Server server, ProjectMeasuresIndex measuresIndex) { + public FormDataAction(UserSession userSession, Server server, DbClient dbClient) { this.userSession = userSession; this.server = server; - this.measuresIndex = measuresIndex; + this.dbClient = dbClient; } @Override @@ -56,13 +58,16 @@ public void handle(Request request, Response response) throws Exception { .checkLoggedIn() .checkIsSystemAdministrator(); - String serverId = server.getId(); - long nloc = measuresIndex.searchTelemetryStatistics().getNcloc(); - FormDataResponse responsePayload = FormDataResponse.newBuilder() - .setNcloc(nloc) - .setServerId(serverId) + .setNcloc(computeNcloc()) + .setServerId(server.getId()) .build(); - WsUtils.writeProtobuf(responsePayload, request, response); + writeProtobuf(responsePayload, request, response); + } + + private long computeNcloc() { + try (DbSession dbSession = dbClient.openSession(false)) { + return dbClient.liveMeasureDao().sumNclocOfBiggestLongLivingBranch(dbSession); + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java index 93fe07f6d40b..a759e0326c5b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java @@ -75,7 +75,6 @@ import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY; import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY; -import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY; import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY; @@ -105,8 +104,8 @@ import static org.sonarqube.ws.client.project.ProjectsWsParameters.FILTER_TAGS; import static org.sonarqube.ws.client.project.ProjectsWsParameters.MAX_PAGE_SIZE; -@ComputeEngineSide @ServerSide +@ComputeEngineSide public class ProjectMeasuresIndex { public static final List SUPPORTED_FACETS = ImmutableList.of( @@ -203,16 +202,15 @@ public ProjectMeasuresStatistics searchTelemetryStatistics() { .order(Terms.Order.count(false)) .subAggregation(sum(FIELD_DISTRIB_NCLOC).field(FIELD_DISTRIB_NCLOC)))); - Stream.of(LINES_KEY, NCLOC_KEY) - .forEach(metric -> request.addAggregation(AggregationBuilders.nested(metric, FIELD_MEASURES) - .subAggregation(AggregationBuilders.filter(metric + "_filter", termQuery(FIELD_MEASURES_KEY, metric)) - .subAggregation(sum(metric + "_filter_sum").field(FIELD_MEASURES_VALUE))))); + request.addAggregation(AggregationBuilders.nested(NCLOC_KEY, FIELD_MEASURES) + .subAggregation(AggregationBuilders.filter(NCLOC_KEY + "_filter", termQuery(FIELD_MEASURES_KEY, NCLOC_KEY)) + .subAggregation(sum(NCLOC_KEY + "_filter_sum").field(FIELD_MEASURES_VALUE)))); ProjectMeasuresStatistics.Builder statistics = ProjectMeasuresStatistics.builder(); SearchResponse response = request.get(); statistics.setProjectCount(response.getHits().getTotalHits()); - Stream.of(LINES_KEY, NCLOC_KEY) + Stream.of(NCLOC_KEY) .map(metric -> (Nested) response.getAggregations().get(metric)) .map(nested -> (Filter) nested.getAggregations().get(nested.getName() + "_filter")) .map(filter -> (Sum) filter.getAggregations().get(filter.getName() + "_sum")) diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresStatistics.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresStatistics.java index 369ac649da08..0012e40383e4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresStatistics.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresStatistics.java @@ -22,19 +22,16 @@ import java.util.Map; import static java.util.Objects.requireNonNull; -import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; public class ProjectMeasuresStatistics { private final long projectCount; - private final long lines; private final long ncloc; private final Map projectCountByLanguage; private final Map nclocByLanguage; private ProjectMeasuresStatistics(Builder builder) { projectCount = builder.projectCount; - lines = builder.lines; ncloc = builder.ncloc; projectCountByLanguage = builder.projectCountByLanguage; nclocByLanguage = builder.nclocByLanguage; @@ -44,10 +41,10 @@ public long getProjectCount() { return projectCount; } - public long getLines() { - return lines; - } - + /** + * @deprecated since 7.2 Global Ncloc computation should rely on org.sonar.db.measure.LiveMeasureDao#countNcloc(org.sonar.db.DbSession) + */ + @Deprecated public long getNcloc() { return ncloc; } @@ -66,7 +63,6 @@ public static Builder builder() { public static class Builder { private Long projectCount; - private Long lines; private Long ncloc; private Map projectCountByLanguage; private Map nclocByLanguage; @@ -81,15 +77,10 @@ public Builder setProjectCount(long projectCount) { } public Builder setSum(String metric, long value) { - switch (metric) { - case LINES_KEY: - this.lines = value; - break; - case NCLOC_KEY: - this.ncloc = value; - break; - default: - throw new IllegalStateException("Metric not supported: " + metric); + if (NCLOC_KEY.equals(metric)) { + this.ncloc = value; + } else { + throw new IllegalStateException("Metric not supported: " + metric); } return this; } @@ -105,7 +96,6 @@ public Builder setNclocByLanguage(Map nclocByLanguage) { public ProjectMeasuresStatistics build() { requireNonNull(projectCount); - requireNonNull(lines); requireNonNull(ncloc); requireNonNull(projectCountByLanguage); requireNonNull(nclocByLanguage); diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java index 5b08138c7298..a8790069333c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java @@ -28,7 +28,6 @@ public class TelemetryData { private final String serverId; private final String version; private final Map plugins; - private final long lines; private final long ncloc; private final long userCount; private final long projectCount; @@ -41,8 +40,7 @@ private TelemetryData(Builder builder) { serverId = builder.serverId; version = builder.version; plugins = builder.plugins; - lines = builder.projectMeasuresStatistics.getLines(); - ncloc = builder.projectMeasuresStatistics.getNcloc(); + ncloc = builder.ncloc; userCount = builder.userCount; projectCount = builder.projectMeasuresStatistics.getProjectCount(); usingBranches = builder.usingBranches; @@ -63,10 +61,6 @@ public Map getPlugins() { return plugins; } - public long getLines() { - return lines; - } - public long getNcloc() { return ncloc; } @@ -106,6 +100,7 @@ static class Builder { private Map plugins; private Database database; private ProjectMeasuresStatistics projectMeasuresStatistics; + private Long ncloc; private Boolean usingBranches; private Builder() { @@ -122,16 +117,24 @@ Builder setVersion(String version) { return this; } - void setUserCount(long userCount) { + Builder setUserCount(long userCount) { this.userCount = userCount; + return this; } - void setPlugins(Map plugins) { + Builder setPlugins(Map plugins) { this.plugins = plugins; + return this; } - void setProjectMeasuresStatistics(ProjectMeasuresStatistics projectMeasuresStatistics) { + Builder setProjectMeasuresStatistics(ProjectMeasuresStatistics projectMeasuresStatistics) { this.projectMeasuresStatistics = projectMeasuresStatistics; + return this; + } + + Builder setNcloc(long ncloc) { + this.ncloc = ncloc; + return this; } Builder setDatabase(Database database) { @@ -149,6 +152,7 @@ TelemetryData build() { requireNonNull(version); requireNonNull(plugins); requireNonNull(projectMeasuresStatistics); + requireNonNull(ncloc); requireNonNull(database); requireNonNull(usingBranches); diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java index 1e35468805a9..1b3df1148cdc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java @@ -21,7 +21,6 @@ import org.sonar.api.utils.text.JsonWriter; -import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; public class TelemetryDataJsonWriter { @@ -50,7 +49,6 @@ public static void writeTelemetryData(JsonWriter json, TelemetryData statistics) json.prop("userCount", statistics.getUserCount()); json.prop("projectCount", statistics.getProjectCount()); json.prop("usingBranches", statistics.isUsingBranches()); - json.prop(LINES_KEY, statistics.getLines()); json.prop(NCLOC_KEY, statistics.getNcloc()); json.name("projectCountByLanguage"); json.beginArray(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java index 8cbca030f519..601b0898092b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.Map; import java.util.function.Function; +import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.platform.Server; import org.sonar.api.server.ServerSide; import org.sonar.core.platform.PluginInfo; @@ -37,6 +38,7 @@ import org.sonar.server.user.index.UserIndex; import org.sonar.server.user.index.UserQuery; +@ComputeEngineSide @ServerSide public class TelemetryDataLoader { private final Server server; @@ -68,6 +70,7 @@ public TelemetryData load() { try (DbSession dbSession = dbClient.openSession(false)) { data.setDatabase(loadDatabaseMetadata(dbSession)); data.setUsingBranches(dbClient.branchDao().hasNonMainBranches(dbSession)); + data.setNcloc(dbClient.liveMeasureDao().sumNclocOfBiggestLongLivingBranch(dbSession)); } return data.build(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/edition/ws/FormDataActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/edition/ws/FormDataActionTest.java index 120ea0c39ba3..7a6e8e68dbc4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/edition/ws/FormDataActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/edition/ws/FormDataActionTest.java @@ -19,55 +19,50 @@ */ package org.sonar.server.edition.ws; -import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import java.io.IOException; -import java.util.Arrays; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.sonar.api.platform.Server; import org.sonar.api.server.ws.WebService; -import org.sonar.server.edition.EditionManagementState; +import org.sonar.db.DbClient; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.metric.MetricDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; -import org.sonar.server.measure.index.ProjectMeasuresIndex; -import org.sonar.server.measure.index.ProjectMeasuresStatistics; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; -import org.sonar.test.JsonAssert; -import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.Editions.FormDataResponse; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.server.edition.EditionManagementState.PendingStatus.NONE; +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; +import static org.sonar.api.measures.Metric.ValueType.INT; +import static org.sonar.test.JsonAssert.assertJson; @RunWith(DataProviderRunner.class) public class FormDataActionTest { + @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); + @Rule + public DbTester db = DbTester.create(); private Server server = mock(Server.class); - private ProjectMeasuresStatistics stats = mock(ProjectMeasuresStatistics.class); - private ProjectMeasuresIndex measuresIndex = mock(ProjectMeasuresIndex.class); - private FormDataAction underTest = new FormDataAction(userSessionRule, server, measuresIndex); - private WsActionTester actionTester = new WsActionTester(underTest); - - @Before - public void setUp() { - when(measuresIndex.searchTelemetryStatistics()).thenReturn(stats); - } + private DbClient dbClient = db.getDbClient(); + private FormDataAction underTest = new FormDataAction(userSessionRule, server, dbClient); + + private WsActionTester ws = new WsActionTester(underTest); @Test - public void verify_definition() { - WebService.Action def = actionTester.getDef(); + public void definition() { + WebService.Action def = ws.getDef(); assertThat(def.key()).isEqualTo("form_data"); assertThat(def.since()).isEqualTo("6.7"); @@ -80,7 +75,7 @@ public void verify_definition() { @Test public void request_fails_if_user_not_logged_in() { userSessionRule.anonymous(); - TestRequest request = actionTester.newRequest(); + TestRequest request = ws.newRequest(); expectedException.expect(UnauthorizedException.class); expectedException.expectMessage("Authentication is required"); @@ -91,7 +86,7 @@ public void request_fails_if_user_not_logged_in() { @Test public void request_fails_if_user_is_not_system_administer() { userSessionRule.logIn(); - TestRequest request = actionTester.newRequest(); + TestRequest request = ws.newRequest(); expectedException.expect(ForbiddenException.class); expectedException.expectMessage("Insufficient privileges"); @@ -100,37 +95,36 @@ public void request_fails_if_user_is_not_system_administer() { } @Test - public void verify_example() { + public void json_example() { userSessionRule.logIn().setSystemAdministrator(); when(server.getId()).thenReturn("uuid"); - when(stats.getNcloc()).thenReturn(12345L); + setNcloc(12345L); - TestRequest request = actionTester.newRequest(); + String result = ws.newRequest().execute().getInput(); - JsonAssert.assertJson(request.execute().getInput()).isSimilarTo(actionTester.getDef().responseExampleAsString()); + assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString()); } @Test - public void returns_server_id_and_nloc() throws IOException { + public void returns_server_id_and_nloc() { userSessionRule.logIn().setSystemAdministrator(); when(server.getId()).thenReturn("myserver"); - when(stats.getNcloc()).thenReturn(1000L); + long ncloc = 256L; + setNcloc(ncloc); FormDataResponse expectedResponse = FormDataResponse.newBuilder() .setServerId("myserver") - .setNcloc(1000L) + .setNcloc(ncloc) .build(); - TestRequest request = actionTester.newRequest().setMediaType(MediaTypes.PROTOBUF); + FormDataResponse result = ws.newRequest().executeProtobuf(FormDataResponse.class); - assertThat(FormDataResponse.parseFrom(request.execute().getInputStream())).isEqualTo(expectedResponse); + assertThat(result).isEqualTo(expectedResponse); } - @DataProvider - public static Object[][] notNonePendingInstallationStatuses() { - return Arrays.stream(EditionManagementState.PendingStatus.values()) - .filter(s -> s != NONE) - .map(s -> new Object[] {s}) - .toArray(Object[][]::new); + private void setNcloc(double ncloc) { + ComponentDto project = db.components().insertMainBranch(); + MetricDto nclocMetric = db.measures().insertMetric(m -> m.setValueType(INT.toString()).setKey(NCLOC_KEY)); + db.measures().insertLiveMeasure(project, nclocMetric, m -> m.setValue(ncloc)); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java index e452edbcf09c..8d8627d429b9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java @@ -1373,18 +1373,16 @@ public void search_tags_with_page_size_at_0() { @Test public void search_statistics() { es.putDocuments(INDEX_TYPE_PROJECT_MEASURES, - newDoc("lines", 10, "ncloc", 20, "coverage", 80) + newDoc("lines", 10, "coverage", 80) .setLanguages(Arrays.asList("java", "cs", "js")) .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 200, "cs", 250, "js", 50)), - newDoc("lines", 20, "ncloc", 30, "coverage", 80) + newDoc("lines", 20, "coverage", 80) .setLanguages(Arrays.asList("java", "python", "kotlin")) .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404))); ProjectMeasuresStatistics result = underTest.searchTelemetryStatistics(); assertThat(result.getProjectCount()).isEqualTo(2); - assertThat(result.getLines()).isEqualTo(30); - assertThat(result.getNcloc()).isEqualTo(50); assertThat(result.getProjectCountByLanguage()).containsOnly( entry("java", 2L), entry("cs", 1L), entry("js", 1L), entry("python", 1L), entry("kotlin", 1L)); assertThat(result.getNclocByLanguage()).containsOnly( diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/ClusterSystemInfoWriterTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/ClusterSystemInfoWriterTest.java index d4d870f41f70..90feb1f3bc4a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/ClusterSystemInfoWriterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/ClusterSystemInfoWriterTest.java @@ -70,7 +70,7 @@ public void writeInfo() throws InterruptedException { + "\"Application Nodes\":[{\"Name\":\"appNodes\",\"\":{\"name\":\"appNodes\"}}]," + "\"Search Nodes\":[{\"Name\":\"searchNodes\",\"\":{\"name\":\"searchNodes\"}}]," + "\"Statistics\":{\"id\":\"\",\"version\":\"\",\"database\":{\"name\":\"\",\"version\":\"\"},\"plugins\":[]," - + "\"userCount\":0,\"projectCount\":0,\"usingBranches\":false,\"lines\":0,\"ncloc\":0,\"projectCountByLanguage\":[],\"nclocByLanguage\":[]}}"); + + "\"userCount\":0,\"projectCount\":0,\"usingBranches\":false,\"ncloc\":0,\"projectCountByLanguage\":[],\"nclocByLanguage\":[]}}"); } private static NodeInfo createNodeInfo(String name) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StandaloneSystemInfoWriterTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StandaloneSystemInfoWriterTest.java index a228ff739ad4..1f2ef6850118 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StandaloneSystemInfoWriterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/StandaloneSystemInfoWriterTest.java @@ -79,7 +79,7 @@ public void write_json() { // response does not contain empty "Section Three" assertThat(writer.toString()).isEqualTo("{\"Health\":\"GREEN\",\"Health Causes\":[],\"Section One\":{\"foo\":\"bar\"},\"Section Two\":{\"one\":1,\"two\":2}," + "\"Statistics\":{\"id\":\"\",\"version\":\"\",\"database\":{\"name\":\"\",\"version\":\"\"},\"plugins\":[],\"userCount\":0,\"projectCount\":0,\"usingBranches\":false," + - "\"lines\":0,\"ncloc\":0,\"projectCountByLanguage\":[],\"nclocByLanguage\":[]}}"); + "\"ncloc\":0,\"projectCountByLanguage\":[],\"nclocByLanguage\":[]}}"); } private void logInAsSystemAdministrator() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java index 0ed4e2289b43..d9171b08155d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java @@ -163,7 +163,7 @@ private void assertDatabaseMetadata(String json) { } @Test - public void exclude_branches() throws IOException { + public void take_biggest_long_living_branches() throws IOException { initTelemetrySettingsToDefaultValues(); settings.setProperty("sonar.telemetry.frequencyInSeconds", "1"); server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4"); @@ -181,7 +181,7 @@ public void exclude_branches() throws IOException { ArgumentCaptor jsonCaptor = ArgumentCaptor.forClass(String.class); verify(client, timeout(2_000).atLeastOnce()).upload(jsonCaptor.capture()); assertJson(jsonCaptor.getValue()).isSimilarTo("{\n" + - " \"ncloc\": 10\n" + + " \"ncloc\": 20\n" + "}\n"); } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/telemetry/telemetry-example.json b/server/sonar-server/src/test/resources/org/sonar/server/telemetry/telemetry-example.json index 5ec6050cba7c..1d80c0c7ed29 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/telemetry/telemetry-example.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/telemetry/telemetry-example.json @@ -22,7 +22,6 @@ "userCount": 3, "projectCount": 2, "usingBranches": true, - "lines": 500, "ncloc": 300, "projectCountByLanguage": [ { diff --git a/tests/src/test/java/org/sonarqube/tests/ce/CeWorkersPauseTest.java b/tests/src/test/java/org/sonarqube/tests/ce/CeWorkersPauseTest.java index fc4f73387d42..56460f7808ad 100644 --- a/tests/src/test/java/org/sonarqube/tests/ce/CeWorkersPauseTest.java +++ b/tests/src/test/java/org/sonarqube/tests/ce/CeWorkersPauseTest.java @@ -34,10 +34,10 @@ import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.XooProjectBuilder; import org.sonarqube.tests.Category4Suite; import org.sonarqube.ws.Ce; import org.sonarqube.ws.client.ce.ActivityStatusRequest; -import util.XooProjectBuilder; import static org.assertj.core.api.Assertions.assertThat; diff --git a/tests/src/test/java/org/sonarqube/tests/component/ModuleTest.java b/tests/src/test/java/org/sonarqube/tests/component/ModuleTest.java index 37029fd7b574..a56ef4b24cf4 100644 --- a/tests/src/test/java/org/sonarqube/tests/component/ModuleTest.java +++ b/tests/src/test/java/org/sonarqube/tests/component/ModuleTest.java @@ -28,10 +28,10 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.XooProjectBuilder; import org.sonarqube.ws.client.components.ShowRequest; import org.sonarqube.ws.client.components.TreeRequest; import org.sonarqube.ws.client.projects.UpdateKeyRequest; -import util.XooProjectBuilder; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java index 407acd2478fe..69070092154f 100644 --- a/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java +++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java @@ -28,10 +28,10 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.XooProjectBuilder; import org.sonarqube.ws.Components.Component; import org.sonarqube.ws.Organizations; import org.sonarqube.ws.client.components.ShowRequest; -import util.XooProjectBuilder; import static org.apache.commons.lang.StringUtils.repeat; import static org.assertj.core.api.Assertions.assertThat; diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java index 1afbc28366a1..b5b9ff2cbc16 100644 --- a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java +++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java @@ -37,6 +37,7 @@ import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.XooProjectBuilder; import org.sonarqube.ws.Components; import org.sonarqube.ws.Organizations; import org.sonarqube.ws.Projects; @@ -49,7 +50,6 @@ import org.sonarqube.ws.client.projects.BulkUpdateKeyRequest; import org.sonarqube.ws.client.projects.UpdateKeyRequest; import util.ItUtils; -import util.XooProjectBuilder; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; diff --git a/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java b/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java index cc81e8e60742..5a9c01d65fee 100644 --- a/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java +++ b/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java @@ -33,13 +33,13 @@ import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.XooProjectBuilder; import org.sonarqube.ws.Ce; import org.sonarqube.ws.Projects; import org.sonarqube.ws.client.ce.ActivityStatusRequest; import org.sonarqube.ws.client.plugins.UninstallRequest; import org.sonarqube.ws.client.qualityprofiles.AddProjectRequest; import util.ItUtils; -import util.XooProjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static util.ItUtils.newOrchestratorBuilder; diff --git a/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryUploadTest.java b/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryUploadTest.java index fd17f3851126..5257a8847cf6 100644 --- a/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryUploadTest.java +++ b/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryUploadTest.java @@ -91,7 +91,6 @@ public void sent_telemetry_data() throws Exception { List plugins = ((List>) json.get("plugins")).stream().map(p -> p.get("name")).collect(Collectors.toList()); assertThat(plugins).contains("xoo"); assertThat(getInteger(json.get("ncloc"))).isEqualTo(13 * 2 + 7); - assertThat(getInteger(json.get("lines"))).isEqualTo(17 * 3); List> projectCountByLanguage = (List>) json.get("projectCountByLanguage"); assertThat(projectCountByLanguage).extracting(p -> p.get("language"), p -> getInteger(p.get("count"))) .contains(tuple("xoo", 2), tuple("xoo2", 1));