diff --git a/src/main/java/com/redhat/ecosystemappeng/onguard/model/osv/Partition.java b/src/main/java/com/redhat/ecosystemappeng/onguard/model/osv/Partition.java new file mode 100644 index 0000000..00d85a4 --- /dev/null +++ b/src/main/java/com/redhat/ecosystemappeng/onguard/model/osv/Partition.java @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.redhat.ecosystemappeng.onguard.model.osv; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +public record Partition(List items, int size) { + + public Stream> stream() { + List> partitions = new ArrayList<>(); + if(items == null) { + return Stream.empty(); + } + int pos = 0; + while(pos < items.size()) { + var to = pos + size; + if(to > items.size()) { + to = items.size(); + } + partitions.add(items.subList(pos, to)); + pos = to; + } + return partitions.stream(); + } +} diff --git a/src/main/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceImpl.java b/src/main/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceImpl.java index 8ff4505..1e63a4b 100644 --- a/src/main/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceImpl.java +++ b/src/main/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceImpl.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.jboss.resteasy.reactive.ClientWebApplicationException; @@ -34,6 +35,7 @@ import com.redhat.ecosystemappeng.onguard.model.VulnerabilityAlias; import com.redhat.ecosystemappeng.onguard.model.osv.OsvVulnerability; import com.redhat.ecosystemappeng.onguard.model.osv.PackageRef; +import com.redhat.ecosystemappeng.onguard.model.osv.Partition; import com.redhat.ecosystemappeng.onguard.model.osv.QueryRequest; import com.redhat.ecosystemappeng.onguard.model.osv.QueryRequestItem; import com.redhat.ecosystemappeng.onguard.model.osv.VulnerabilityRef; @@ -49,6 +51,7 @@ public class VulnerabilityServiceImpl implements VulnerabilityService { private static final Logger LOGGER = LoggerFactory.getLogger(VulnerabilityServiceImpl.class); + private static final int MAX_OSV_BATCH = 1000; @Inject VulnerabilityRepository repository; @@ -80,6 +83,15 @@ public List find(List aliases, boolean reload) { @Override public Map> findByPurls(List purls, boolean reload) { + return new Partition(purls, MAX_OSV_BATCH) + .stream() + .parallel() + .map(p -> this.processBatch(p, reload)) + .flatMap(m -> m.entrySet().stream()) + .collect(Collectors.toMap(a -> a.getKey(), a -> a.getValue())); + } + + private Map> processBatch(List purls, boolean reload) { List queries = purls.stream().map(purl -> new QueryRequestItem(new PackageRef(purl))).toList(); var response = osvApi.queryBatch(new QueryRequest(queries)); Map> vulnerabilities = new HashMap<>(); @@ -89,7 +101,12 @@ public Map> findByPurls(List purls, boolean if (resultItem == null || resultItem.vulns() == null) { vulnerabilities.put(purl, Collections.emptyList()); } else { - vulnerabilities.put(purl, find(resultItem.vulns().stream().map(VulnerabilityRef::id).toList(), reload)); + var vulns = find(resultItem.vulns().stream().map(VulnerabilityRef::id).toList(), reload); + if(vulns == null) { + vulnerabilities.put(purl, Collections.emptyList()); + } else { + vulnerabilities.put(purl, vulns); + } } } return vulnerabilities; @@ -109,7 +126,7 @@ public void ingestNvdVulnerability(Vulnerability vuln) { builder = Vulnerability.builder(vuln); } var osvVuln = getOsvVulnerabilityData(vuln.cveId()); - if(osvVuln != null) { + if (osvVuln != null) { builder.affected(osvVuln.affected()).summary(osvVuln.summary()).description(osvVuln.description()); } repository.save(builder.build()); @@ -120,16 +137,16 @@ private Vulnerability load(VulnerabilityAlias vulnAlias, boolean reload) { return vulnAlias.vulnerability(); } var vuln = getOsvVulnerabilityData(vulnAlias.alias()); - if(vuln == null || vuln.cveId() == null) { + if (vuln == null || vuln.cveId() == null) { return null; } var metrics = nvdService.getCveMetrics(vuln.cveId()); var updated = Vulnerability.builder(vuln); - if(metrics != null) { + if (metrics != null) { updated.metrics(metrics); } var existing = repository.get(vuln.cveId()); - if(existing != null && existing.hasData()) { + if (existing != null && existing.hasData()) { updated.created(existing.created()).lastModified(new Date()); } else { updated.created(new Date()); diff --git a/src/main/java/com/redhat/ecosystemappeng/onguard/service/nvd/NvdFallbackService.java b/src/main/java/com/redhat/ecosystemappeng/onguard/service/nvd/NvdFallbackService.java index bf8db56..de2efcb 100644 --- a/src/main/java/com/redhat/ecosystemappeng/onguard/service/nvd/NvdFallbackService.java +++ b/src/main/java/com/redhat/ecosystemappeng/onguard/service/nvd/NvdFallbackService.java @@ -41,58 +41,58 @@ @ApplicationScoped public class NvdFallbackService implements FallbackHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(NvdFallbackService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(NvdFallbackService.class); - @Inject - VulnerabilityRepository repository; + @Inject + VulnerabilityRepository repository; - @Inject - ManagedExecutor executor; + @Inject + ManagedExecutor executor; - @Inject - NvdService nvdService; + @Inject + NvdService nvdService; - @ConfigProperty(name = "CircuitBreaker/delay", defaultValue = "30") - Long delay; + @ConfigProperty(name = "CircuitBreaker/delay", defaultValue = "30") + Long delay; - private void updateMetrics(String cveId) { - var metrics = nvdService.getCveMetrics(cveId); - if (metrics == null) { - LOGGER.debug("Unable to retrieve metrics from NVD for CVE {}", cveId); - return; - } - var vuln = repository.get(cveId); - if (vuln != null) { - var newVuln = Vulnerability.builder(vuln).metrics(metrics).lastModified(new Date()).build(); - repository.save(newVuln); - repository.setAliases(List.of(cveId), cveId); - } + private void updateMetrics(String cveId) { + var metrics = nvdService.getCveMetrics(cveId); + if (metrics == null) { + LOGGER.debug("Unable to retrieve metrics from NVD for CVE {}", cveId); + return; } + var vuln = repository.get(cveId); + if (vuln != null) { + var newVuln = Vulnerability.builder(vuln).metrics(metrics).lastModified(new Date()).build(); + repository.save(newVuln); + repository.setAliases(List.of(cveId), cveId); + } + } - @Override - public NvdResponse handle(ExecutionContext context) { - if(shouldHandle(context.getFailure())) { - Uni.createFrom() - .item((String) context.getParameters()[0]) - .onItem().delayIt().by(Duration.ofSeconds(delay)).invoke(cveId -> updateMetrics(cveId)) - .runSubscriptionOn(executor).subscribeAsCompletionStage(); - } - return new NvdResponse(0, 0, 0, null, null, new Date(), Collections.emptyList()); + @Override + public NvdResponse handle(ExecutionContext context) { + if (shouldHandle(context.getFailure())) { + Uni.createFrom() + .item((String) context.getParameters()[0]) + .onItem().delayIt().by(Duration.ofSeconds(delay)).invoke(cveId -> updateMetrics(cveId)) + .runSubscriptionOn(executor).subscribeAsCompletionStage(); } + return new NvdResponse(0, 0, 0, null, null, new Date(), Collections.emptyList()); + } - private boolean shouldHandle(Throwable failure) { - if(failure == null) { - return true; - } - var cause = failure; - if(failure.getCause() != null && !(failure instanceof WebApplicationException)) { - cause = failure.getCause(); - } - if(cause instanceof WebApplicationException) { - var error = (WebApplicationException) cause; - var status = error.getResponse().getStatus(); - return status != 404; - } - return true; + private boolean shouldHandle(Throwable failure) { + if (failure == null) { + return true; + } + var cause = failure; + if (failure.getCause() != null && !(failure instanceof WebApplicationException)) { + cause = failure.getCause(); + } + if (cause instanceof WebApplicationException) { + var error = (WebApplicationException) cause; + var status = error.getResponse().getStatus(); + return status != 404; } + return true; + } } diff --git a/src/test/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceTest.java b/src/test/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceTest.java new file mode 100644 index 0000000..d513cba --- /dev/null +++ b/src/test/java/com/redhat/ecosystemappeng/onguard/service/VulnerabilityServiceTest.java @@ -0,0 +1,127 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.redhat.ecosystemappeng.onguard.service; + +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.resetAllRequests; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; + +import org.jboss.resteasy.reactive.ClientWebApplicationException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.redhat.ecosystemappeng.onguard.model.Vulnerability; +import com.redhat.ecosystemappeng.onguard.model.VulnerabilityAlias; +import com.redhat.ecosystemappeng.onguard.repository.VulnerabilityRepository; +import com.redhat.ecosystemappeng.onguard.test.InjectWireMock; +import com.redhat.ecosystemappeng.onguard.test.WireMockExtensions; + +import io.quarkus.test.InjectMock; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import jakarta.inject.Inject; + +@QuarkusTest +@QuarkusTestResource(WireMockExtensions.class) +public class VulnerabilityServiceTest { + + @InjectWireMock + WireMockServer server; + + @InjectMock + VulnerabilityRepository repository; + + static { + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + } + + @AfterEach + public void reset() { + server.resetRequests(); + } + + @Inject + VulnerabilityService vulnerabilityService; + + @Test + void testFindByPurls_Empty() { + var result = vulnerabilityService.findByPurls(null, false); + assertTrue(result.isEmpty()); + + result = vulnerabilityService.findByPurls(Collections.emptyList(), false); + assertTrue(result.isEmpty()); + + server.verify(0, postRequestedFor(urlEqualTo(WireMockExtensions.OSV_API_PATH))); + } + + @Test + void testFindByPurls_NoVulns() { + var purl = "pkg:maven/org.mvnpm.at.vaadin/select@24.0.5?type=jar"; + var purls = List.of(purl); + var results = vulnerabilityService.findByPurls(purls, false); + + assertFalse(results.isEmpty()); + assertEquals(purls.size(), results.size()); + var result = results.get(purl); + assertNotNull(result); + assertTrue(result.isEmpty()); + + server.verify(1, postRequestedFor(urlEqualTo(WireMockExtensions.OSV_API_PATH))); + } + + @Test + void testFindByPurls_Success() { + var purls = List.of(WireMockExtensions.PURL_WITH_VULNS); + var alias = "GHSA-hr8g-6v94-x4m9"; + var vulnerability = new Vulnerability("cve-001", null, null, null, null, null, null); + when(repository.listByAliases(anyList())).thenReturn(List.of(new VulnerabilityAlias(alias, vulnerability))); + + var results = vulnerabilityService.findByPurls(purls, false); + + assertFalse(results.isEmpty()); + assertEquals(purls.size(), results.size()); + var result = results.get(WireMockExtensions.PURL_WITH_VULNS); + assertNotNull(result); + assertEquals(1, result.size()); + var found = result.get(0); + assertEquals(vulnerability, found); + + server.verify(1, postRequestedFor(urlEqualTo(WireMockExtensions.OSV_API_PATH))); + } + + @Test + void testFindByPurls_Error() { + var purls = List.of(WireMockExtensions.PURL_WITH_ERROR); + + assertThrows(ClientWebApplicationException.class, () -> vulnerabilityService.findByPurls(purls, false)); + + server.verify(1, postRequestedFor(urlEqualTo(WireMockExtensions.OSV_API_PATH))); + } +} diff --git a/src/test/java/com/redhat/ecosystemappeng/onguard/test/WireMockExtensions.java b/src/test/java/com/redhat/ecosystemappeng/onguard/test/WireMockExtensions.java index b1691af..18711b6 100644 --- a/src/test/java/com/redhat/ecosystemappeng/onguard/test/WireMockExtensions.java +++ b/src/test/java/com/redhat/ecosystemappeng/onguard/test/WireMockExtensions.java @@ -18,105 +18,144 @@ package com.redhat.ecosystemappeng.onguard.test; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.serverError; import static com.github.tomakehurst.wiremock.client.WireMock.status; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.junit.jupiter.api.Assertions.fail; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.jetty.http.HttpHeader; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.stubbing.Scenario; +import com.redhat.ecosystemappeng.onguard.model.osv.PackageRef; +import com.redhat.ecosystemappeng.onguard.model.osv.QueryRequest; +import com.redhat.ecosystemappeng.onguard.model.osv.QueryRequestItem; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import jakarta.ws.rs.core.MediaType; public class WireMockExtensions implements QuarkusTestResourceLifecycleManager { - private static final String API_KEY_PARAM = "apiKey"; - public static final String CVE_PARAM = "cveId"; - public static final String NVD_API_KEY = "nvd-api-123"; - public static final String VALID_CVE = "CVE-2022-24684"; - public static final String ERROR_503_CVE = "FAIL_WITH_503"; - public static final String NOT_FOUND = "not_found"; + private static final String API_KEY_PARAM = "apiKey"; + public static final String CVE_PARAM = "cveId"; + public static final String NVD_API_KEY = "nvd-api-123"; + public static final String VALID_CVE = "CVE-2022-24684"; + public static final String ERROR_503_CVE = "FAIL_WITH_503"; + public static final String NOT_FOUND = "not_found"; - public static final String NVD_API_PATH = "/rest/json/cves/2.0"; + public static final String NVD_API_PATH = "/rest/json/cves/2.0"; + public static final String OSV_API_PATH = "/v1/querybatch"; + public static final String PURL_WITH_VULNS = "pkg:maven/io.smallrye.config/smallrye-config@3.3.2.redhat-00001?repository_url=https%3A%2F%2Fmaven.repository.redhat.com%2Fga%2F&type=jar"; + public static final String PURL_WITH_ERROR = "pkg:maven/com.example/error@0.0.0?type=jar"; - private final WireMockServer server = new WireMockServer(options().dynamicPort()); + private final WireMockServer server = new WireMockServer(options().dynamicPort()); - @Override - public Map start() { - server.start(); + @Override + public Map start() { + server.start(); - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam(CVE_PARAM, equalTo(VALID_CVE )) - .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam(CVE_PARAM, equalTo(VALID_CVE)) + .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") .withHeader(HttpHeader.CONTENT_TYPE.asString(), MediaType.APPLICATION_JSON))); - - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam(CVE_PARAM, equalTo(ERROR_503_CVE)) - .willReturn(status(503))); - - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam(CVE_PARAM, equalTo(NOT_FOUND)) - .willReturn(status(404))); - - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam("startIndex", equalTo("0")) - .withQueryParam("resultsPerPage", equalTo("200")) - .withQueryParam("lastModStartDate", equalTo("start_date")) - .withQueryParam("lastModEndDate", equalTo("end_date")) - .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") + + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam(CVE_PARAM, equalTo(ERROR_503_CVE)) + .willReturn(status(503))); + + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam(CVE_PARAM, equalTo(NOT_FOUND)) + .willReturn(status(404))); + + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam("startIndex", equalTo("0")) + .withQueryParam("resultsPerPage", equalTo("200")) + .withQueryParam("lastModStartDate", equalTo("start_date")) + .withQueryParam("lastModEndDate", equalTo("end_date")) + .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") .withHeader(HttpHeader.CONTENT_TYPE.asString(), MediaType.APPLICATION_JSON))); - - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .inScenario("List Retry") - .whenScenarioStateIs(Scenario.STARTED) - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam("startIndex", equalTo("10")) - .withQueryParam("resultsPerPage", equalTo("200")) - .withQueryParam("lastModStartDate", equalTo("start_date")) - .withQueryParam("lastModEndDate", equalTo("end_date")) - .willReturn(status(503)) - .willSetStateTo("Next")); - - server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) - .inScenario("List Retry") - .whenScenarioStateIs("Next") - .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) - .withQueryParam("startIndex", equalTo("10")) - .withQueryParam("resultsPerPage", equalTo("200")) - .withQueryParam("lastModStartDate", equalTo("start_date")) - .withQueryParam("lastModEndDate", equalTo("end_date")) - .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") + + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .inScenario("List Retry") + .whenScenarioStateIs(Scenario.STARTED) + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam("startIndex", equalTo("10")) + .withQueryParam("resultsPerPage", equalTo("200")) + .withQueryParam("lastModStartDate", equalTo("start_date")) + .withQueryParam("lastModEndDate", equalTo("end_date")) + .willReturn(status(503)) + .willSetStateTo("Next")); + + server.stubFor(get(urlPathEqualTo(NVD_API_PATH)) + .inScenario("List Retry") + .whenScenarioStateIs("Next") + .withHeader(API_KEY_PARAM, equalTo(NVD_API_KEY)) + .withQueryParam("startIndex", equalTo("10")) + .withQueryParam("resultsPerPage", equalTo("200")) + .withQueryParam("lastModStartDate", equalTo("start_date")) + .withQueryParam("lastModEndDate", equalTo("end_date")) + .willReturn(ok().withBodyFile("nvd-data/" + VALID_CVE + ".json") .withHeader(HttpHeader.CONTENT_TYPE.asString(), MediaType.APPLICATION_JSON))); - Map props = new HashMap<>(); - props.put("quarkus.rest-client.nvd-api.url", server.baseUrl()); - props.put("api.nvd.apikey", NVD_API_KEY); - return props; + stubOsv(); + + Map props = new HashMap<>(); + props.put("quarkus.rest-client.nvd-api.url", server.baseUrl()); + props.put("quarkus.rest-client.osv-api.url", server.baseUrl()); + props.put("api.nvd.apikey", NVD_API_KEY); + return props; + } + + private void stubOsv() { + var mapper = new ObjectMapper(); + var reqWithVulns = new QueryRequest(List.of(new QueryRequestItem(new PackageRef(PURL_WITH_VULNS)))); + var reqWithError = new QueryRequest(List.of(new QueryRequestItem(new PackageRef(PURL_WITH_ERROR)))); + + try { + server.stubFor(post(urlPathEqualTo(OSV_API_PATH)) + .willReturn(ok().withBodyFile("osv-data/empty.json") + .withHeader(HttpHeader.CONTENT_TYPE.asString(), MediaType.APPLICATION_JSON))); + + server.stubFor(post(urlPathEqualTo(OSV_API_PATH)) + .withRequestBody(equalToJson(mapper.writeValueAsString(reqWithVulns))) + .willReturn(ok().withBodyFile("osv-data/vulnerability.json") + .withHeader(HttpHeader.CONTENT_TYPE.asString(), MediaType.APPLICATION_JSON))); + + server.stubFor(post(urlPathEqualTo(OSV_API_PATH)) + .withRequestBody(equalToJson(mapper.writeValueAsString(reqWithError))).willReturn(serverError())); + + } catch (JsonProcessingException e) { + fail(e); } + } - - @Override - public void stop() { - if(server != null) { - server.stop(); - } + @Override + public void stop() { + if (server != null) { + server.stop(); } + } - @Override - public void inject(TestInjector testInjector) { - testInjector.injectIntoFields(server, new TestInjector.AnnotatedAndMatchesType(InjectWireMock.class, WireMockServer.class)); - } + @Override + public void inject(TestInjector testInjector) { + testInjector.injectIntoFields(server, + new TestInjector.AnnotatedAndMatchesType(InjectWireMock.class, WireMockServer.class)); + } } diff --git a/src/test/resources/__files/osv-data/empty.json b/src/test/resources/__files/osv-data/empty.json new file mode 100644 index 0000000..b86b034 --- /dev/null +++ b/src/test/resources/__files/osv-data/empty.json @@ -0,0 +1,5 @@ +{ + "results": [ + {} + ] +} \ No newline at end of file diff --git a/src/test/resources/__files/osv-data/vulnerability.json b/src/test/resources/__files/osv-data/vulnerability.json new file mode 100644 index 0000000..cef7174 --- /dev/null +++ b/src/test/resources/__files/osv-data/vulnerability.json @@ -0,0 +1,12 @@ +{ + "results": [ + { + "vulns": [ + { + "id": "GHSA-hr8g-6v94-x4m9", + "modified": "2024-02-18T05:32:43.784092Z" + } + ] + } + ] +} \ No newline at end of file