From 36e3d5aec104de0b0dfd5cf90394c62318ae99bf Mon Sep 17 00:00:00 2001 From: Wojciech Wajerowicz Date: Tue, 11 Oct 2022 14:40:11 +0200 Subject: [PATCH] SONAR-12456 Add Security Hotspots to project badges. SONAR-12456 Fix existing issues in modfied files. SONAR-12456 Remove some duplication in tests. --- .../sonar/server/badge/ws/MeasureAction.java | 12 ++-- .../server/badge/ws/MeasureActionTest.java | 72 +++++++++++++------ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java index 2369ace6df1..058363dc165 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java @@ -53,6 +53,7 @@ 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.NCLOC_KEY; import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY; +import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_KEY; import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY; import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY; import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY; @@ -88,22 +89,23 @@ public class MeasureAction implements ProjectBadgesWsAction { .put(SQALE_RATING_KEY, "maintainability") .put(ALERT_STATUS_KEY, "quality gate") .put(RELIABILITY_RATING_KEY, "reliability") + .put(SECURITY_HOTSPOTS_KEY, "security hotspots") .put(SECURITY_RATING_KEY, "security") .put(TECHNICAL_DEBT_KEY, "technical debt") .put(VULNERABILITIES_KEY, "vulnerabilities") .build(); - private static final Map QUALITY_GATE_MESSAGE_BY_STATUS = new EnumMap<>(ImmutableMap.of( + private static final Map QUALITY_GATE_MESSAGE_BY_STATUS = new EnumMap<>(Map.of( OK, "passed", WARN, "warning", ERROR, "failed")); - private static final Map COLOR_BY_QUALITY_GATE_STATUS = new EnumMap<>(ImmutableMap.of( + private static final Map COLOR_BY_QUALITY_GATE_STATUS = new EnumMap<>(Map.of( OK, Color.QUALITY_GATE_OK, WARN, Color.QUALITY_GATE_WARN, ERROR, Color.QUALITY_GATE_ERROR)); - private static final Map COLOR_BY_RATING = new EnumMap<>(ImmutableMap.of( + private static final Map COLOR_BY_RATING = new EnumMap<>(Map.of( A, Color.RATING_A, B, Color.RATING_B, C, Color.RATING_C, @@ -200,8 +202,8 @@ public class MeasureAction implements ProjectBadgesWsAction { return svgGenerator.generateBadge(METRIC_NAME_BY_KEY.get(metric.getKey()), value, color); } - private static PARAM getNonNullValue(LiveMeasureDto measure, Function function) { - PARAM value = function.apply(measure); + private static

P getNonNullValue(LiveMeasureDto measure, Function function) { + P value = function.apply(measure); checkState(value != null, "Measure has not been found"); return value; } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java index f5d070570d8..811dc5c69fd 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java @@ -49,6 +49,7 @@ import org.sonar.server.badge.ws.SvgGenerator.Color; import org.sonar.server.component.ComponentFinder; import org.sonar.server.measure.Rating; import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; @@ -57,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.measures.CoreMetrics.BUGS_KEY; import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY; +import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_KEY; import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY; import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY; import static org.sonar.api.measures.Metric.Level.ERROR; @@ -92,7 +94,7 @@ public class MeasureActionTest { new SvgGenerator())); @Before - public void before(){ + public void before() { mapSettings.setProperty(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, false); } @@ -100,8 +102,7 @@ public class MeasureActionTest { public void int_measure() { ComponentDto project = db.components().insertPublicProject(); userSession.registerComponents(project); - MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(10_000d)); + MetricDto metric = createIntMetricAndMeasure(project, BUGS_KEY, 10_000); TestResponse response = ws.newRequest() .setParam("project", project.getKey()) @@ -207,6 +208,24 @@ public class MeasureActionTest { checkWithIfNoneMatchHeader(project, metric, response); } + @Test + public void security_hotspots() { + ComponentDto project = db.components().insertPublicProject(); + userSession.registerComponents(project); + MetricDto metric = createIntMetricAndMeasure(project, SECURITY_HOTSPOTS_KEY, 42); + + TestResponse response = ws.newRequest() + .setParam("project", project.getKey()) + .setParam("metric", metric.getKey()) + .execute(); + + checkSvg(response, "security hotspots", "42", DEFAULT); + + // Second call with If-None-Match must return 304 + checkWithIfNoneMatchHeader(project, metric, response); + + } + @Test public void display_deprecated_warning_quality_gate() { ComponentDto project = db.components().insertPublicProject(); @@ -226,8 +245,8 @@ public class MeasureActionTest { public void measure_on_non_main_branch() { ComponentDto project = db.components().insertPublicProject(p -> p.setPrivate(false)); userSession.registerComponents(project); - MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); - db.measures().insertLiveMeasure(project, metric, m -> m.setValue(5_000d)); + MetricDto metric = createIntMetricAndMeasure(project, BUGS_KEY, 5_000); + ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH)); db.measures().insertLiveMeasure(branch, metric, m -> m.setValue(10_000d)); @@ -255,8 +274,7 @@ public class MeasureActionTest { public void measure_on_application() { ComponentDto application = db.components().insertPublicApplication(); userSession.registerComponents(application); - MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); - db.measures().insertLiveMeasure(application, metric, m -> m.setValue(10_000d)); + MetricDto metric = createIntMetricAndMeasure(application, BUGS_KEY, 10_000); TestResponse response = ws.newRequest() .setParam("project", application.getKey()) @@ -342,7 +360,7 @@ public class MeasureActionTest { } @DataProvider - public static Object[][] publicProject_forceAuth_accessGranted(){ + public static Object[][] publicProject_forceAuth_accessGranted() { return new Object[][] { // public project, force auth : works depending on token's validity {true, true, true, true}, @@ -363,12 +381,11 @@ public class MeasureActionTest { @Test @UseDataProvider("publicProject_forceAuth_accessGranted") public void badge_accessible_on_private_project_with_token(boolean publicProject, boolean forceAuth, - boolean validToken, boolean accessGranted) throws ParseException { + boolean validToken, boolean accessGranted) throws ParseException { ComponentDto projectAsComponent = publicProject ? db.components().insertPublicProject() : db.components().insertPrivateProject(); userSession.registerComponents(projectAsComponent); - MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); + MetricDto metric = createIntMetricAndMeasure(projectAsComponent, BUGS_KEY, 10_000); - db.measures().insertLiveMeasure(projectAsComponent, metric, m -> m.setValue(10_000d)); ProjectDto project = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), projectAsComponent.getKey()) .orElseThrow(() -> new IllegalStateException("project not found")); @@ -385,9 +402,9 @@ public class MeasureActionTest { .setParam("token", validToken ? token : "invalid-token") .execute(); - if(accessGranted){ + if (accessGranted) { checkSvg(response, "bugs", "10k", DEFAULT); - }else{ + } else { checkError(response, "Project has not been found"); } } @@ -413,10 +430,11 @@ public class MeasureActionTest { MetricDto metric = createQualityGateMetric(); db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN")); + TestRequest request = ws.newRequest() + .setParam("project", project.getKey()) + .setParam("metric", metric.getKey()); assertThatThrownBy(() -> { - ws.newRequest() - .setParam("project", project.getKey()) - .setParam("metric", metric.getKey()) + request .execute(); }) .isInstanceOf(IllegalArgumentException.class) @@ -430,10 +448,12 @@ public class MeasureActionTest { MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name())); db.measures().insertLiveMeasure(project, metric, m -> m.setValue(null)); + TestRequest request = ws.newRequest() + .setParam("project", project.getKey()) + .setParam("metric", metric.getKey()); + assertThatThrownBy(() -> { - ws.newRequest() - .setParam("project", project.getKey()) - .setParam("metric", metric.getKey()) + request .execute(); }) .isInstanceOf(IllegalStateException.class) @@ -445,10 +465,12 @@ public class MeasureActionTest { ComponentDto project = db.components().insertPublicProject(); userSession.registerComponents(project); + TestRequest request = ws.newRequest() + .setParam("project", project.getKey()) + .setParam("metric", BUGS_KEY); + assertThatThrownBy(() -> { - ws.newRequest() - .setParam("project", project.getKey()) - .setParam("metric", BUGS_KEY) + request .execute(); }) .isInstanceOf(IllegalStateException.class) @@ -507,4 +529,10 @@ public class MeasureActionTest { private MetricDto createQualityGateMetric() { return db.measures().insertMetric(m -> m.setKey(CoreMetrics.ALERT_STATUS_KEY).setValueType(LEVEL.name())); } + + private MetricDto createIntMetricAndMeasure(ComponentDto project, String key, Integer value) { + MetricDto metric = db.measures().insertMetric(m -> m.setKey(key).setValueType(INT.name())); + db.measures().insertLiveMeasure(project, metric, m -> m.setValue(value.doubleValue())); + return metric; + } } -- 2.39.5