浏览代码

SONAR-22034 New Endpoints to get JREs metadata and download JRE

master
antoine.vinot 2 周前
父节点
当前提交
d0eae15ce5
共有 15 个文件被更改,包括 699 次插入9 次删除
  1. 1
    0
      server/sonar-webserver-webapi-v2/build.gradle
  2. 1
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
  3. 51
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultJresController.java
  4. 67
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/JresController.java
  5. 30
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/response/JreInfoRestResponse.java
  6. 23
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/response/package-info.java
  7. 33
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/JresHandler.java
  8. 148
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/JresHandlerImpl.java
  9. 23
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/package-info.java
  10. 14
    0
      server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java
  11. 132
    0
      server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultJresControllerTest.java
  12. 3
    3
      server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultVersionControllerTest.java
  13. 130
    0
      server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/JresHandlerImplTest.java
  14. 21
    6
      server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/config/PlatformLevel4WebConfigTest.java
  15. 22
    0
      server/sonar-webserver-webapi-v2/src/test/resources/jres-metadata-tests.json

+ 1
- 0
server/sonar-webserver-webapi-v2/build.gradle 查看文件

@@ -17,6 +17,7 @@ dependencies {

testImplementation 'javax.servlet:javax.servlet-api'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testImplementation 'org.junit.jupiter:junit-jupiter-params'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.mockito:mockito-junit-jupiter'
testImplementation 'org.skyscreamer:jsonassert:1.5.1'

+ 1
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java 查看文件

@@ -48,6 +48,7 @@ public class WebApiEndpoints {

public static final String ANALYSIS_ENDPOINT = "/analysis";
public static final String VERSION_ENDPOINT = ANALYSIS_ENDPOINT + "/version";
public static final String JRE_ENDPOINT = ANALYSIS_ENDPOINT + "/jres";

private WebApiEndpoints() {
}

+ 51
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/DefaultJresController.java 查看文件

@@ -0,0 +1,51 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.controller;

import java.util.List;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;
import org.sonar.server.v2.api.analysis.service.JresHandler;
import org.springframework.core.io.InputStreamResource;

public class DefaultJresController implements JresController {

private final JresHandler jresHandler;

public DefaultJresController(JresHandler jresHandler) {
this.jresHandler = jresHandler;
}

@Override
public List<JreInfoRestResponse> getJresMetadata(String os, String arch) {
return jresHandler.getJresMetadata(os, arch);
}

@Override
public JreInfoRestResponse getJreMetadata(String id) {
return jresHandler.getJreMetadata(id);
}

@Override
public InputStreamResource downloadJre(String id) {
JreInfoRestResponse jreInfoRestResponse = jresHandler.getJreMetadata(id);
return new InputStreamResource(jresHandler.getJreBinary(jreInfoRestResponse.filename()));
}

}

+ 67
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/controller/JresController.java 查看文件

@@ -0,0 +1,67 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import java.util.List;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;
import org.springframework.core.io.InputStreamResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import static io.swagger.v3.oas.annotations.enums.ParameterIn.PATH;
import static org.sonar.server.v2.WebApiEndpoints.JRE_ENDPOINT;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;

@RequestMapping(value = JRE_ENDPOINT, produces = APPLICATION_JSON_VALUE)
@ResponseStatus(OK)
@RestController
public interface JresController {

String OS_PARAM_DESCRIPTION = "Filter the JRE by operating system. Accepted values are 'windows', 'linux', 'macos', 'alpine' (case-insensitive), with some aliases";
String ARCH_PARAM_DESCRIPTION = "Filter the JRE by CPU architecture. Accepted values are 'x64' and 'aarch64' (case-insensitive), with some aliases.";
String GET_JRE_DESCRIPTION =
"This endpoint return the JRE metadata by default. To download the JRE binary asset, set the Accept header of the request to 'application/octet-stream'.";
String GET_JRE_SUMMARY = "JRE download/metadata";
String ID_PARAM_DESCRIPTION = "The ID of the JRE";

@GetMapping
@Operation(summary = "All JREs metadata", description = "Get metadata of all available JREs")
List<JreInfoRestResponse> getJresMetadata(
@RequestParam(value = "os", required = false) @Parameter(description = OS_PARAM_DESCRIPTION) String os,
@RequestParam(value = "arch", required = false) @Parameter(description = ARCH_PARAM_DESCRIPTION) String arch);

@GetMapping(value = "/{id}")
@Operation(summary = GET_JRE_SUMMARY, description = GET_JRE_DESCRIPTION)
JreInfoRestResponse getJreMetadata(
@PathVariable(value = "id") @Parameter(description = ID_PARAM_DESCRIPTION, required = true, in = PATH) String id);

@GetMapping(value = "/{id}", produces = APPLICATION_OCTET_STREAM_VALUE)
@Operation(summary = GET_JRE_SUMMARY, description = GET_JRE_DESCRIPTION)
InputStreamResource downloadJre(
@PathVariable(value = "id") @Parameter(description = ID_PARAM_DESCRIPTION, required = true, in = PATH) String id);
}

+ 30
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/response/JreInfoRestResponse.java 查看文件

@@ -0,0 +1,30 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.response;

public record JreInfoRestResponse(
String id,
String filename,
String sha256,
String javaPath,
String os,
String arch
) {
}

+ 23
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/response/package-info.java 查看文件

@@ -0,0 +1,23 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.v2.api.analysis.response;

import javax.annotation.ParametersAreNonnullByDefault;

+ 33
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/JresHandler.java 查看文件

@@ -0,0 +1,33 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.service;

import java.io.InputStream;
import java.util.List;
import javax.annotation.Nullable;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;

public interface JresHandler {
List<JreInfoRestResponse> getJresMetadata(@Nullable String os, @Nullable String arch);

JreInfoRestResponse getJreMetadata(String id);

InputStream getJreBinary(String jreFilename);
}

+ 148
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/JresHandlerImpl.java 查看文件

@@ -0,0 +1,148 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;

import static java.lang.String.join;
import static org.apache.commons.lang.StringUtils.isBlank;

public class JresHandlerImpl implements JresHandler {

private static final String JRES_METADATA_FILENAME = "jres-metadata.json";

private final String jresMetadataFilename;
private final Map<String, JreInfoRestResponse> metadata = new HashMap<>();

public JresHandlerImpl() {
this(JRES_METADATA_FILENAME);
}

@VisibleForTesting
public JresHandlerImpl(String jresMetadataFilename) {
this.jresMetadataFilename = jresMetadataFilename;
}

@PostConstruct
void initMetadata() {
metadata.clear();
readJresMetadata().forEach(jre -> metadata.put(jre.id(), jre));
}

private List<JreInfoRestResponse> readJresMetadata() {
ObjectMapper objectMapper = new ObjectMapper();
try (InputStream is = getClass().getClassLoader().getResourceAsStream(jresMetadataFilename)) {
return objectMapper.readValue(is, objectMapper.getTypeFactory().constructCollectionType(List.class, JreInfoRestResponse.class));
} catch (IOException ioException) {
throw new UncheckedIOException(ioException);
}
}

@Override
public List<JreInfoRestResponse> getJresMetadata(@Nullable String os, @Nullable String arch) {
Predicate<JreInfoRestResponse> osFilter = isBlank(os) ? jre -> true : (jre -> OS.from(jre.os()) == OS.from(os));
Predicate<JreInfoRestResponse> archFilter = isBlank(arch) ? jre -> true : (jre -> Arch.from(jre.arch()) == Arch.from(arch));
return metadata.values().stream()
.filter(osFilter)
.filter(archFilter)
.toList();
}

@Override
public JreInfoRestResponse getJreMetadata(String id) {
return Optional.ofNullable(metadata.get(id))
.orElseThrow(() -> new NotFoundException("JRE not found for id: " + id));
}

@Override
public InputStream getJreBinary(String jreFilename) {
try {
return new FileInputStream("jres/" + jreFilename);
} catch (FileNotFoundException fileNotFoundException) {
throw new NotFoundException(String.format("Unable to find JRE '%s'", jreFilename));
}
}

enum OS {
WINDOWS("win", "windows", "win32"),
LINUX("linux"),
MACOS("mac", "macos", "darwin"),
ALPINE("alpine");

private final List<String> aliases;

OS(String... aliases) {
this.aliases = Arrays.stream(aliases).toList();
}

private static OS from(String alias) {
return Arrays.stream(values())
.filter(os -> os.aliases.contains(alias))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(String.format("Unsupported OS: '%s'. Supported values are '%s'", alias, join(", ", supportedValues()))));
}

private static List<String> supportedValues() {
return Arrays.stream(values())
.flatMap(os -> os.aliases.stream())
.toList();
}
}

enum Arch {
X64("x86_64", "x86-64", "amd64", "x64"),
AARCH64("arm64", "aarch64");

private final List<String> aliases;

Arch(String... aliases) {
this.aliases = Arrays.stream(aliases).toList();
}

private static Arch from(String alias) {
return Arrays.stream(values())
.filter(arch -> arch.aliases.contains(alias))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(String.format("Unsupported architecture: '%s'. Supported values are '%s'", alias, join(", ", supportedValues()))));
}

private static List<String> supportedValues() {
return Arrays.stream(values())
.flatMap(arch -> arch.aliases.stream())
.toList();
}
}
}

+ 23
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/analysis/service/package-info.java 查看文件

@@ -0,0 +1,23 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.v2.api.analysis.service;

import javax.annotation.ParametersAreNonnullByDefault;

+ 14
- 0
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java 查看文件

@@ -43,8 +43,12 @@ import org.sonar.server.platform.NodeInformation;
import org.sonar.server.rule.RuleDescriptionFormatter;
import org.sonar.server.user.SystemPasscode;
import org.sonar.server.user.UserSession;
import org.sonar.server.v2.api.analysis.controller.DefaultJresController;
import org.sonar.server.v2.api.analysis.controller.DefaultVersionController;
import org.sonar.server.v2.api.analysis.controller.JresController;
import org.sonar.server.v2.api.analysis.controller.VersionController;
import org.sonar.server.v2.api.analysis.service.JresHandler;
import org.sonar.server.v2.api.analysis.service.JresHandlerImpl;
import org.sonar.server.v2.api.dop.controller.DefaultDopSettingsController;
import org.sonar.server.v2.api.dop.controller.DopSettingsController;
import org.sonar.server.v2.api.gitlab.config.controller.DefaultGitlabConfigurationController;
@@ -159,4 +163,14 @@ public class PlatformLevel4WebConfig {
return new DefaultVersionController(server);
}

@Bean
public JresHandler jresHandler() {
return new JresHandlerImpl();
}

@Bean
public JresController jresController(JresHandler jresHandler) {
return new DefaultJresController(jresHandler);
}

}

+ 132
- 0
server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultJresControllerTest.java 查看文件

@@ -0,0 +1,132 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.controller;

import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;
import org.sonar.server.v2.api.analysis.service.JresHandler;
import org.springframework.test.web.servlet.MockMvc;

import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.server.v2.WebApiEndpoints.JRE_ENDPOINT;
import static org.sonar.server.v2.api.ControllerTester.getMockMvc;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class DefaultJresControllerTest {

private final JresHandler jresHandler = mock(JresHandler.class);

private final MockMvc mockMvc = getMockMvc(new DefaultJresController(jresHandler));

@ParameterizedTest
@MethodSource("osAndArch")
void getJres_shoudlReturnMetadaAsJson(String os, String arch) throws Exception {
JreInfoRestResponse metadata1 = new JreInfoRestResponse("id_1", "filename_1", "sha256_1", "javaPath_1", "os_1", "arch_1");
JreInfoRestResponse metadata2 = new JreInfoRestResponse("id_2", "filename_2", "sha256_2", "javaPath_2", "os_2", "arch_2");
when(jresHandler.getJresMetadata(os, arch)).thenReturn(List.of(metadata1, metadata2));
String expectedJson =
"""
[
{
"id": "id_1",
"filename": "filename_1",
"sha256": "sha256_1",
"javaPath": "javaPath_1",
"os": "os_1",
"arch": "arch_1"
},
{
"id": "id_2",
"filename": "filename_2",
"sha256": "sha256_2",
"javaPath": "javaPath_2",
"os": "os_2",
"arch": "arch_2"
}
]
""";

mockMvc.perform(get(JRE_ENDPOINT)
.param("os", os)
.param("arch", arch))
.andExpect(status().isOk())
.andExpect(content().json(expectedJson));
}

@Test
void getJres_shoudlReturnEmptyJsonArray_whenNoResults() throws Exception {
when(jresHandler.getJresMetadata(null, null)).thenReturn(List.of());

mockMvc.perform(get(JRE_ENDPOINT))
.andExpect(status().isOk())
.andExpect(content().json("[]"));
}

private static Stream<Arguments> osAndArch() {
return Stream.of(
arguments(null, null),
arguments("windows", null),
arguments(null, "x64"),
arguments("linux", "aarch64")
);
}

@Test
void getJre_shouldReturnMetadataAsJson() throws Exception {
String anyId = "anyId";
JreInfoRestResponse jreInfoRestResponse = new JreInfoRestResponse(anyId, "filename", "sha256", "javaPath", "os", "arch");
when(jresHandler.getJreMetadata(anyId)).thenReturn(jreInfoRestResponse);
String expectedJson = "{\"id\":\"" + anyId + "\",\"filename\":\"filename\",\"sha256\":\"sha256\",\"javaPath\":\"javaPath\",\"os\":\"os\",\"arch\":\"arch\"}";

mockMvc.perform(get(JRE_ENDPOINT + "/" + anyId))
.andExpect(status().isOk())
.andExpect(content().json(expectedJson));
}

@Test
void getJre_shouldDownloadJre_whenHeaderIsOctetStream() throws Exception {
String anyId = "anyId";
String anyFilename = "anyFilename";
JreInfoRestResponse jreInfoRestResponse = new JreInfoRestResponse(anyId, anyFilename, "sha256", "javaPath", "os", "arch");
when(jresHandler.getJreMetadata(anyId)).thenReturn(jreInfoRestResponse);
byte[] anyBinary = {1, 2, 3};

when(jresHandler.getJreBinary(anyFilename)).thenReturn(new ByteArrayInputStream(anyBinary));

mockMvc.perform(get(JRE_ENDPOINT + "/" + anyId)
.header("Accept", APPLICATION_OCTET_STREAM_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_OCTET_STREAM))
.andExpect(content().bytes(anyBinary));
}

}

+ 3
- 3
server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/controller/DefaultVersionControllerTest.java 查看文件

@@ -19,7 +19,7 @@
*/
package org.sonar.server.v2.api.analysis.controller;

import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.sonar.api.platform.Server;
import org.springframework.test.web.servlet.MockMvc;

@@ -31,14 +31,14 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class DefaultVersionControllerTest {
class DefaultVersionControllerTest {

private final Server server = mock(Server.class);

private final MockMvc mockMvc = getMockMvc(new DefaultVersionController(server));

@Test
public void getVersion_shouldReturnServerVersion() throws Exception {
void getVersion_shouldReturnServerVersion() throws Exception {
String serverVersion = "10.6";
when(server.getVersion()).thenReturn(serverVersion);


+ 130
- 0
server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/analysis/service/JresHandlerImplTest.java 查看文件

@@ -0,0 +1,130 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.v2.api.analysis.service;

import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.v2.api.analysis.response.JreInfoRestResponse;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.params.provider.Arguments.arguments;

class JresHandlerImplTest {

private static final Map<String, JreInfoRestResponse> JRE_METADATA = Map.of(
"1", new JreInfoRestResponse("1", "jre1", "checksum1", "java1", "alpine", "aarch64"),
"2", new JreInfoRestResponse("2", "jre2", "checksum2", "java2", "linux", "aarch64"),
"3", new JreInfoRestResponse("3", "jre3", "checksum3", "java3", "alpine", "x64")
);

private static final JresHandlerImpl jresHandler = new JresHandlerImpl("jres-metadata-tests.json");

@BeforeAll
static void setup() {
jresHandler.initMetadata();
}

@Test
void getJresMetadata_shouldReturnAllMetadata_whenNoFiltering() {
List<JreInfoRestResponse> result = jresHandler.getJresMetadata(null, null);

assertThat(result).extracting(JreInfoRestResponse::id).containsExactly("1", "2", "3");
}

@ParameterizedTest
@MethodSource("filteredMetadata")
void getJresMetadata_shouldReturnFilteredMetadata_whenFiltering(String os, String arch, JreInfoRestResponse expected) {
List<JreInfoRestResponse> resultList = jresHandler.getJresMetadata(os, arch);

assertThat(resultList).hasSize(1);
JreInfoRestResponse result = resultList.get(0);
assertThat(result).usingRecursiveComparison().isEqualTo(expected);
}

@Test
void getJresMetadata_shouldFail_whenFilteredWithUnsupportedOsValue() {
String anyUnsupportedOS = "not-supported";

assertThatThrownBy(() -> jresHandler.getJresMetadata(anyUnsupportedOS, null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageStartingWith("Unsupported OS: '" + anyUnsupportedOS + "'");
}

@Test
void getJresMetadata_shouldFail_whenFilteredWithUnsupportedArchValue() {
String anyUnsupportedArch = "not-supported";

assertThatThrownBy(() -> jresHandler.getJresMetadata(null, anyUnsupportedArch))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageStartingWith("Unsupported architecture: '" + anyUnsupportedArch + "'");
}

private static Stream<Arguments> filteredMetadata() {
return Stream.of(
arguments("alpine", "aarch64", JRE_METADATA.get("1")),
arguments("linux", null, JRE_METADATA.get("2")),
arguments(null, "x64", JRE_METADATA.get("3"))
);
}

@Test
void getJresMetadata_shouldReturnEmptyList_whenNoMetadata() {
List<JreInfoRestResponse> result = jresHandler.getJresMetadata("windows", "x64");
assertThat(result).isEmpty();
}

@Test
void getJresMetadata_shouldReturnEmptyList_whenNoFilteringAndNoMetadata() {
JresHandlerImpl noMetadataHandler = new JresHandlerImpl("");
List<JreInfoRestResponse> result = noMetadataHandler.getJresMetadata(null, null);
assertThat(result).isEmpty();
}

@ParameterizedTest
@ValueSource(strings = {"1", "2", "3"})
void getJreMetadata(String id) {
JreInfoRestResponse result = jresHandler.getJreMetadata(id);

assertThat(result).usingRecursiveComparison().isEqualTo(JRE_METADATA.get(id));
}

@Test
void getJreMetadata_shouldFail_whenJreNotFound() {
assertThatThrownBy(() -> jresHandler.getJreMetadata("4"))
.isInstanceOf(NotFoundException.class)
.hasMessage("JRE not found for id: 4");
}

@Test
void getJreBinary_shouldFail_whenFileNotFound() {
assertThatThrownBy(() -> jresHandler.getJreBinary("jre1"))
.isInstanceOf(NotFoundException.class)
.hasMessage("Unable to find JRE 'jre1'");
}
}

+ 21
- 6
server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/config/PlatformLevel4WebConfigTest.java 查看文件

@@ -19,20 +19,35 @@
*/
package org.sonar.server.v2.config;

import org.junit.Test;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.api.platform.Server;
import org.sonar.server.v2.api.analysis.controller.DefaultJresController;
import org.sonar.server.v2.api.analysis.controller.DefaultVersionController;
import org.sonar.server.v2.api.analysis.service.JresHandler;
import org.sonar.server.v2.api.analysis.service.JresHandlerImpl;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.mock;

public class PlatformLevel4WebConfigTest {

private final PlatformLevel4WebConfig platformLevel4WebConfig = new PlatformLevel4WebConfig();
private static final PlatformLevel4WebConfig platformLevel4WebConfig = new PlatformLevel4WebConfig();

@Test
public void versionController() {
assertThat(platformLevel4WebConfig.versionController(mock(Server.class))).isNotNull()
.isInstanceOf(DefaultVersionController.class);
private static Stream<Arguments> components() {
return Stream.of(
arguments(platformLevel4WebConfig.versionController(mock(Server.class)), DefaultVersionController.class),
arguments(platformLevel4WebConfig.jresHandler(), JresHandlerImpl.class),
arguments(platformLevel4WebConfig.jresController(mock(JresHandler.class)), DefaultJresController.class)
);
}

@ParameterizedTest
@MethodSource("components")
void components_shouldBeInjectedInPlatformLevel4WebConfig(Object component, Class<?> instanceClass) {
assertThat(component).isNotNull().isInstanceOf(instanceClass);
}
}

+ 22
- 0
server/sonar-webserver-webapi-v2/src/test/resources/jres-metadata-tests.json 查看文件

@@ -0,0 +1,22 @@
[ {
"id" : "1",
"filename" : "jre1",
"sha256" : "checksum1",
"javaPath" : "java1",
"os" : "alpine",
"arch" : "aarch64"
}, {
"id" : "2",
"filename" : "jre2",
"sha256" : "checksum2",
"javaPath" : "java2",
"os" : "linux",
"arch" : "aarch64"
}, {
"id" : "3",
"filename" : "jre3",
"sha256" : "checksum3",
"javaPath" : "java3",
"os" : "alpine",
"arch" : "x64"
} ]

正在加载...
取消
保存