diff --git a/pom.xml b/pom.xml index 6af1b2fe..e5f4c8f1 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,10 @@ 5.0.0-alpha.14 gridsuite org.gridsuite:shortcircuit-analysis-server + + 1.7.0 + 1.34.0 + 1.15.0 @@ -87,6 +91,24 @@ + + com.powsybl + powsybl-ws-commons + ${powsybl-ws-commons.version} + + + + org.gridsuite + gridsuite-computation + ${gridsuite-computation.version} + + + + org.gridsuite + gridsuite-filter + ${gridsuite-filter.version} + + com.squareup.okhttp3 okhttp-bom diff --git a/src/main/java/org/gridsuite/shortcircuit/server/PropertyServerNameProvider.java b/src/main/java/org/gridsuite/shortcircuit/server/PropertyServerNameProvider.java new file mode 100644 index 00000000..b5a6a044 --- /dev/null +++ b/src/main/java/org/gridsuite/shortcircuit/server/PropertyServerNameProvider.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server; + +import com.powsybl.ws.commons.error.ServerNameProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author Hugo Marcellin + */ +@Component +public class PropertyServerNameProvider implements ServerNameProvider { + private final String name; + + public PropertyServerNameProvider(@Value("${spring.application.name:shortcircuit-server}") String name) { + this.name = name; + } + + @Override + public String serverName() { + return name; + } +} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/shortcircuit/server/RestResponseEntityExceptionHandler.java deleted file mode 100644 index 039f3fbd..00000000 --- a/src/main/java/org/gridsuite/shortcircuit/server/RestResponseEntityExceptionHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2024, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.shortcircuit.server; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -/** - * @author Ghazwa Rehili - */ -@ControllerAdvice -public class RestResponseEntityExceptionHandler { - @ExceptionHandler(ShortCircuitException.class) - protected ResponseEntity handleShortCircuitException(ShortCircuitException exception) { - return switch (exception.getType()) { - case RESULT_NOT_FOUND, PARAMETERS_NOT_FOUND -> ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); - case INVALID_EXPORT_PARAMS -> ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exception.getMessage()); - case BUS_OUT_OF_VOLTAGE, FILE_EXPORT_ERROR, MISSING_EXTENSION_DATA, INCONSISTENT_VOLTAGE_LEVELS -> - ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage()); - }; - } -} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitApplication.java b/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitApplication.java index 01447ee8..d961585e 100644 --- a/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitApplication.java +++ b/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitApplication.java @@ -7,6 +7,7 @@ package org.gridsuite.shortcircuit.server; import com.powsybl.network.store.client.NetworkStoreService; +import org.gridsuite.computation.error.ComputationExceptionHandler; import org.gridsuite.computation.service.NotificationService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -15,7 +16,7 @@ * @author Etienne Homer */ @SuppressWarnings("checkstyle:HideUtilityClassConstructor") -@SpringBootApplication(scanBasePackageClasses = { ShortCircuitApplication.class, NetworkStoreService.class, NotificationService.class }) +@SpringBootApplication(scanBasePackageClasses = {ShortCircuitApplication.class, NetworkStoreService.class, NotificationService.class, ComputationExceptionHandler.class}) public class ShortCircuitApplication { public static void main(String[] args) { SpringApplication.run(ShortCircuitApplication.class, args); diff --git a/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitException.java b/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitException.java deleted file mode 100644 index e1ea3688..00000000 --- a/src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitException.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2024, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package org.gridsuite.shortcircuit.server; - -import lombok.Getter; - -import java.util.Objects; - -/** - * @author David SARTORI - */ -@Getter -public class ShortCircuitException extends RuntimeException { - - public enum Type { - BUS_OUT_OF_VOLTAGE, - RESULT_NOT_FOUND, - INVALID_EXPORT_PARAMS, - FILE_EXPORT_ERROR, - MISSING_EXTENSION_DATA, - INCONSISTENT_VOLTAGE_LEVELS, - PARAMETERS_NOT_FOUND - } - - private final Type type; - - public ShortCircuitException(Type type) { - super(Objects.requireNonNull(type.name())); - this.type = type; - } - - public ShortCircuitException(Type type, String message) { - super(message); - this.type = type; - } - -} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/error/ShortCircuitException.java b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortCircuitException.java new file mode 100644 index 00000000..f2722e0f --- /dev/null +++ b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortCircuitException.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server.error; + +import com.powsybl.ws.commons.error.AbstractBusinessException; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +import java.util.Objects; + +/** + * @author David SARTORI + */ +@Getter +public class ShortCircuitException extends AbstractBusinessException { + + private final ShortcircuitBusinessErrorCode errorCode; + + public ShortCircuitException(ShortcircuitBusinessErrorCode errorCode, String message) { + super(Objects.requireNonNull(message, "message must not be null")); + this.errorCode = Objects.requireNonNull(errorCode, "errorCode must not be null"); + } + + @NotNull + @Override + public ShortcircuitBusinessErrorCode getBusinessErrorCode() { + return errorCode; + } +} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitBusinessErrorCode.java b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitBusinessErrorCode.java new file mode 100644 index 00000000..5058e440 --- /dev/null +++ b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitBusinessErrorCode.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package org.gridsuite.shortcircuit.server.error; + +import com.powsybl.ws.commons.error.BusinessErrorCode; + +/** + * @author Hugo Marcellin + */ +public enum ShortcircuitBusinessErrorCode implements BusinessErrorCode { + BUS_OUT_OF_VOLTAGE("shortcircuit.busOutOfVoltage"), + MISSING_EXTENSION_DATA("shortcircuit.missingExtensionData"), + INCONSISTENT_VOLTAGE_LEVELS("shortcircuit.inconsistentVoltageLevels"),; + + private final String code; + + ShortcircuitBusinessErrorCode(String code) { + this.code = code; + } + + public String value() { + return code; + } +} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandler.java b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandler.java new file mode 100644 index 00000000..cb894ba5 --- /dev/null +++ b/src/main/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandler.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server.error; + +import com.powsybl.ws.commons.error.AbstractBusinessExceptionHandler; +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import com.powsybl.ws.commons.error.ServerNameProvider; +import jakarta.servlet.http.HttpServletRequest; +import lombok.NonNull; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +/** + * @author Hugo Marcellin + */ + +@ControllerAdvice +public class ShortcircuitExceptionHandler extends AbstractBusinessExceptionHandler { + protected ShortcircuitExceptionHandler(ServerNameProvider serverNameProvider) { + super(serverNameProvider); + } + + @Override + protected @NonNull ShortcircuitBusinessErrorCode getBusinessCode(ShortCircuitException e) { + return e.getBusinessErrorCode(); + } + + @Override + protected HttpStatus mapStatus(ShortcircuitBusinessErrorCode businessErrorCode) { + return switch (businessErrorCode) { + case BUS_OUT_OF_VOLTAGE, INCONSISTENT_VOLTAGE_LEVELS, MISSING_EXTENSION_DATA -> + HttpStatus.INTERNAL_SERVER_ERROR; + }; + } + + @ExceptionHandler(ShortCircuitException.class) + protected ResponseEntity handleShortcircuitException( + ShortCircuitException exception, HttpServletRequest request) { + return super.handleDomainException(exception, request); + } +} diff --git a/src/main/java/org/gridsuite/shortcircuit/server/service/FilterService.java b/src/main/java/org/gridsuite/shortcircuit/server/service/FilterService.java index d3be9f01..a47e2ed7 100644 --- a/src/main/java/org/gridsuite/shortcircuit/server/service/FilterService.java +++ b/src/main/java/org/gridsuite/shortcircuit/server/service/FilterService.java @@ -14,6 +14,7 @@ import org.gridsuite.computation.service.AbstractFilterService; import org.gridsuite.filter.utils.EquipmentType; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; import java.util.*; @@ -22,10 +23,10 @@ @Slf4j public class FilterService extends AbstractFilterService { - public FilterService( - NetworkStoreService networkStoreService, - @Value("${gridsuite.services.filter-server.base-uri:http://filter-server/}") String filterServerBaseUri) { - super(networkStoreService, filterServerBaseUri); + public FilterService(RestTemplateBuilder restTemplateBuilder, + NetworkStoreService networkStoreService, + @Value("${gridsuite.services.filter-server.base-uri:http://filter-server/}") String filterServerBaseUri) { + super(restTemplateBuilder, networkStoreService, filterServerBaseUri); } public Optional getResourceFilter(@NonNull UUID networkUuid, @NonNull String variantId, @NonNull GlobalFilter globalFilter) { diff --git a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitParametersService.java b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitParametersService.java index 0038b77b..5ddb6046 100644 --- a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitParametersService.java +++ b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitParametersService.java @@ -6,15 +6,14 @@ */ package org.gridsuite.shortcircuit.server.service; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; - +import com.powsybl.commons.config.PlatformConfig; +import com.powsybl.commons.parameters.Parameter; +import com.powsybl.commons.parameters.ParameterScope; +import com.powsybl.shortcircuit.ShortCircuitAnalysisProvider; +import lombok.Getter; +import lombok.NonNull; import org.apache.commons.lang3.tuple.Pair; -import org.gridsuite.shortcircuit.server.ShortCircuitException; +import org.gridsuite.computation.error.ComputationException; import org.gridsuite.shortcircuit.server.dto.ShortCircuitParametersInfos; import org.gridsuite.shortcircuit.server.dto.ShortCircuitParametersValues; import org.gridsuite.shortcircuit.server.entities.parameters.ShortCircuitParametersEntity; @@ -24,13 +23,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.powsybl.commons.config.PlatformConfig; -import com.powsybl.commons.parameters.Parameter; -import com.powsybl.commons.parameters.ParameterScope; -import com.powsybl.shortcircuit.ShortCircuitAnalysisProvider; +import java.util.*; +import java.util.stream.Collectors; -import lombok.Getter; -import lombok.NonNull; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; /** * @author Sylvain Bouzols @@ -93,7 +89,7 @@ public Optional getParametersValues(UUID parameter public ShortCircuitParametersValues getParametersValues(UUID parametersUuid) { return parametersRepository.findById(parametersUuid) - .map(this::toShortCircuitParametersValues).orElseThrow(() -> new ShortCircuitException(ShortCircuitException.Type.PARAMETERS_NOT_FOUND, + .map(this::toShortCircuitParametersValues).orElseThrow(() -> new ComputationException(PARAMETERS_NOT_FOUND, "ShortCircuit parameters '" + parametersUuid + "' not found")); } diff --git a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitService.java b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitService.java index 4120576b..a316cec7 100644 --- a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitService.java +++ b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitService.java @@ -14,13 +14,13 @@ import com.univocity.parsers.csv.CsvWriter; import com.univocity.parsers.csv.CsvWriterSettings; import org.apache.commons.lang3.StringUtils; +import org.gridsuite.computation.error.ComputationException; import org.gridsuite.computation.dto.GlobalFilter; import org.gridsuite.computation.dto.ResourceFilterDTO; import org.gridsuite.computation.s3.ComputationS3Service; import org.gridsuite.computation.service.AbstractComputationService; import org.gridsuite.computation.service.NotificationService; import org.gridsuite.computation.service.UuidGeneratorService; -import org.gridsuite.shortcircuit.server.ShortCircuitException; import org.gridsuite.shortcircuit.server.dto.*; import org.gridsuite.shortcircuit.server.entities.*; import org.slf4j.Logger; @@ -34,6 +34,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.text.NumberFormat; import java.util.*; @@ -43,8 +44,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_EXPORT_PARAMS; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.RESULT_NOT_FOUND; import static org.gridsuite.computation.utils.FilterUtils.fromStringFiltersToDTO; -import static org.gridsuite.shortcircuit.server.ShortCircuitException.Type.*; /** * @author Etienne Homer @@ -253,16 +255,16 @@ public byte[] exportToCsv(ShortCircuitAnalysisResult result, CsvExportParams csv csvWriter.close(); return outputStream.toByteArray(); } catch (IOException e) { - throw new ShortCircuitException(FILE_EXPORT_ERROR, e.getMessage()); + throw new UncheckedIOException("Error occurred while writing data to csv file", e); } } public byte[] getZippedCsvExportResult(UUID resultUuid, ShortCircuitAnalysisResult result, CsvExportParams csvExportParams) { if (result == null) { - throw new ShortCircuitException(RESULT_NOT_FOUND, "The short circuit analysis result '" + resultUuid + "' does not exist"); + throw new ComputationException(RESULT_NOT_FOUND, "The short circuit analysis result '" + resultUuid + "' does not exist"); } if (Objects.isNull(csvExportParams) || Objects.isNull(csvExportParams.csvHeader()) || Objects.isNull(csvExportParams.enumValueTranslations())) { - throw new ShortCircuitException(INVALID_EXPORT_PARAMS, "Missing information to export short-circuit result as csv: file headers and enum translation must be provided"); + throw new ComputationException(INVALID_EXPORT_PARAMS, "Missing information to export short-circuit result as csv: file headers and enum translation must be provided"); } return exportToCsv(result, csvExportParams); } diff --git a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerService.java b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerService.java index c65acf4b..5ef5188d 100644 --- a/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerService.java +++ b/src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerService.java @@ -15,7 +15,7 @@ import com.powsybl.shortcircuit.*; import org.gridsuite.computation.s3.ComputationS3Service; import org.gridsuite.computation.service.*; -import org.gridsuite.shortcircuit.server.ShortCircuitException; +import org.gridsuite.shortcircuit.server.error.ShortCircuitException; import org.gridsuite.shortcircuit.server.dto.ShortCircuitAnalysisStatus; import org.gridsuite.shortcircuit.server.dto.ShortCircuitLimits; import org.gridsuite.shortcircuit.server.dto.ShortCircuitParametersValues; @@ -31,7 +31,9 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import static org.gridsuite.shortcircuit.server.ShortCircuitException.Type.*; +import static org.gridsuite.shortcircuit.server.error.ShortcircuitBusinessErrorCode.BUS_OUT_OF_VOLTAGE; +import static org.gridsuite.shortcircuit.server.error.ShortcircuitBusinessErrorCode.INCONSISTENT_VOLTAGE_LEVELS; +import static org.gridsuite.shortcircuit.server.error.ShortcircuitBusinessErrorCode.MISSING_EXTENSION_DATA; import static org.gridsuite.shortcircuit.server.service.ShortCircuitResultContext.HEADER_BUS_ID; /** @@ -198,7 +200,7 @@ public void postRun(ShortCircuitRunContext runContext, AtomicReference resultContext, Exception exception, AtomicReference rootReporter) { - if (exception instanceof ShortCircuitException shortCircuitException && shortCircuitException.getType() == INCONSISTENT_VOLTAGE_LEVELS) { + if (exception instanceof ShortCircuitException shortCircuitException && shortCircuitException.getBusinessErrorCode() == INCONSISTENT_VOLTAGE_LEVELS) { postRun(resultContext.getRunContext(), rootReporter, null); sendResultMessage(resultContext, null); } diff --git a/src/test/java/org/gridsuite/shortcircuit/server/PropertyServerNameProviderTest.java b/src/test/java/org/gridsuite/shortcircuit/server/PropertyServerNameProviderTest.java new file mode 100644 index 00000000..95b93dbd --- /dev/null +++ b/src/test/java/org/gridsuite/shortcircuit/server/PropertyServerNameProviderTest.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mohamed Ben-rejeb {@literal } + */ +class PropertyServerNameProviderTest { + + @Test + void returnsProvidedName() { + PropertyServerNameProvider provider = new PropertyServerNameProvider("custom-server"); + assertThat(provider.serverName()).isEqualTo("custom-server"); + } +} diff --git a/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersControllerTest.java b/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersControllerTest.java index 68ef5467..73ef4b09 100644 --- a/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersControllerTest.java +++ b/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersControllerTest.java @@ -38,16 +38,19 @@ import java.util.UUID; import java.util.stream.Stream; -import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.doThrow; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @ExtendWith({ MockitoExtension.class }) -@WebMvcTest(controllers = { ShortCircuitParametersController.class }) +@WebMvcTest(controllers = { ShortCircuitParametersController.class, PropertyServerNameProvider.class }) class ShortCircuitParametersControllerTest implements WithAssertions { private final String defaultParametersJson; diff --git a/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersITest.java b/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersITest.java index c3954aa7..5aca485a 100644 --- a/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersITest.java +++ b/src/test/java/org/gridsuite/shortcircuit/server/ShortCircuitParametersITest.java @@ -56,9 +56,13 @@ import static org.hamcrest.Matchers.matchesPattern; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.log; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @@ -359,21 +363,31 @@ void duplicateParameters() throws Exception { @ParameterizedTest @MethodSource("testWithInvalidParametersArgArgs") - void testWithInvalidParametersArg(final RequestBuilder requestBuilder, final ResultMatcher statusResult) throws Exception { - mockMvc.perform(requestBuilder).andDo(log()) - .andExpectAll(statusResult, content().bytes(new byte[0])); + void testWithInvalidParametersArg(final RequestBuilder requestBuilder, final ResultMatcher statusResult, final boolean throwsException, final Integer expectedStatus) throws Exception { + if (!throwsException) { + mockMvc.perform(requestBuilder).andDo(log()) + .andExpectAll(statusResult, content().bytes(new byte[0])); + } else { + mockMvc.perform(requestBuilder).andDo(log()) + .andExpectAll(statusResult, content().contentType(MediaType.APPLICATION_PROBLEM_JSON), + jsonPath("$.status").value(expectedStatus), + jsonPath("$.server").exists(), + jsonPath("$.path").exists(), + jsonPath("$.detail").exists(), + jsonPath("$.timestamp").exists()); + } } private static Stream testWithInvalidParametersArgArgs() { return Stream.of( - Arguments.of(get("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound()), - Arguments.of(delete("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound()), - Arguments.of(post("/v1/parameters"), status().isBadRequest()), - Arguments.of(post("/v1/parameters").content("{}"), status().isBadRequest()), - Arguments.of(post("/v1/parameters").contentType(MediaType.TEXT_PLAIN).content("{}"), status().isBadRequest()), - Arguments.of(post("/v1/parameters").queryParam(DUPLICATE_FROM, ""), status().isBadRequest()), - Arguments.of(post("/v1/parameters").queryParam(DUPLICATE_FROM, UUID.randomUUID().toString()), status().isNotFound()), - Arguments.of(put("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound()) + Arguments.of(get("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound(), false, null), + Arguments.of(delete("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound(), false, null), + Arguments.of(post("/v1/parameters"), status().isBadRequest(), true, 400), + Arguments.of(post("/v1/parameters").content("{}"), status().isBadRequest(), true, 400), + Arguments.of(post("/v1/parameters").contentType(MediaType.TEXT_PLAIN).content("{}"), status().isBadRequest(), true, 400), + Arguments.of(post("/v1/parameters").queryParam(DUPLICATE_FROM, ""), status().isBadRequest(), true, 400), + Arguments.of(post("/v1/parameters").queryParam(DUPLICATE_FROM, UUID.randomUUID().toString()), status().isNotFound(), false, null), + Arguments.of(put("/v1/parameters/{parametersUuid}", UUID.randomUUID()), status().isNotFound(), false, null) ); } diff --git a/src/test/java/org/gridsuite/shortcircuit/server/ShortcircuitBusinessErrorCodeTest.java b/src/test/java/org/gridsuite/shortcircuit/server/ShortcircuitBusinessErrorCodeTest.java new file mode 100644 index 00000000..6c22fcde --- /dev/null +++ b/src/test/java/org/gridsuite/shortcircuit/server/ShortcircuitBusinessErrorCodeTest.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server; + +import org.gridsuite.shortcircuit.server.error.ShortcircuitBusinessErrorCode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.assertj.core.api.Assertions.assertThat; +/** + * @author Hugo Marcellin + */ + +class ShortcircuitBusinessErrorCodeTest { + @ParameterizedTest + @EnumSource(ShortcircuitBusinessErrorCode.class) + void valueMatchesEnumName(ShortcircuitBusinessErrorCode code) { + assertThat(code.value()).startsWith("shortcircuit."); + } +} diff --git a/src/test/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandlerTest.java b/src/test/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandlerTest.java new file mode 100644 index 00000000..e6a08f79 --- /dev/null +++ b/src/test/java/org/gridsuite/shortcircuit/server/error/ShortcircuitExceptionHandlerTest.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.shortcircuit.server.error; + +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.shortcircuit.server.error.ShortcircuitBusinessErrorCode.BUS_OUT_OF_VOLTAGE; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Hugo Marcellin + */ +class ShortcircuitExceptionHandlerTest { + + private ShortcircuitExceptionHandler handler; + + @BeforeEach + void setUp() { + handler = new ShortcircuitExceptionHandler(() -> "shortcircuit"); + } + + @Test + void mapsInteralErrorBusinessErrorToStatus() { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/results-endpoint/uuid"); + ShortCircuitException exception = new ShortCircuitException(BUS_OUT_OF_VOLTAGE, "Bus out of voltage"); + ResponseEntity response = handler.handleShortcircuitException(exception, request); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertEquals("shortcircuit.busOutOfVoltage", response.getBody().getBusinessErrorCode()); + } +} diff --git a/src/test/java/org/gridsuite/shortcircuit/server/service/FilterServiceTest.java b/src/test/java/org/gridsuite/shortcircuit/server/service/FilterServiceTest.java index ca08e7c6..06974f73 100644 --- a/src/test/java/org/gridsuite/shortcircuit/server/service/FilterServiceTest.java +++ b/src/test/java/org/gridsuite/shortcircuit/server/service/FilterServiceTest.java @@ -34,6 +34,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -61,12 +62,15 @@ class FilterServiceTest { @MockitoBean private NetworkStoreService networkStoreService; + @Autowired + RestTemplateBuilder restTemplateBuilder; + @Autowired private FilterService filterService; @BeforeEach void setUp(final MockWebServer mockWebServer) throws Exception { - filterService = new FilterService(networkStoreService, initMockWebServer(mockWebServer)); + filterService = new FilterService(restTemplateBuilder, networkStoreService, initMockWebServer(mockWebServer)); } private static ExpertFilter createTestExpertFilter() { diff --git a/src/test/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerServiceTest.java b/src/test/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerServiceTest.java index 460beeea..c8aef18b 100644 --- a/src/test/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerServiceTest.java +++ b/src/test/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerServiceTest.java @@ -22,8 +22,9 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.WithAssertions; -import org.gridsuite.computation.ComputationException; +import org.gridsuite.computation.error.ComputationException; import org.gridsuite.computation.dto.ReportInfos; + import org.gridsuite.computation.s3.ComputationS3Service; import org.gridsuite.computation.service.ExecutionService; import org.gridsuite.computation.service.NotificationService;