From 40ac415171818ad7d1afaae67190d52a813f5061 Mon Sep 17 00:00:00 2001 From: empassaro Date: Fri, 23 Aug 2024 12:34:17 +0200 Subject: [PATCH 1/7] SELC-4840 feat: added Ivass interceptor and utils to handle zip --- .../exception/InternalException.java | 4 + connector/rest/pom.xml | 9 ++ .../decoder/RestTemplateErrorHandler.java | 30 ++++++ .../rest/interceptor/IvassInterceptor.java | 29 +++++ .../rest/model/IvassDataTemplate.java | 36 +++++++ .../connector/rest/utils/IvassUtils.java | 67 ++++++++++++ .../connector/rest/utils/IvassUtilsTest.java | 102 ++++++++++++++++++ connector/rest/src/test/resources/empty.zip | Bin 0 -> 22 bytes .../resources/ivass-open-data-malformed.csv | 2 + .../src/test/resources/ivass-open-data.csv | 3 + .../rest/src/test/resources/one_file.zip | Bin 0 -> 159 bytes 11 files changed, 282 insertions(+) create mode 100644 connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandler.java create mode 100644 connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptor.java create mode 100644 connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/model/IvassDataTemplate.java create mode 100644 connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java create mode 100644 connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java create mode 100644 connector/rest/src/test/resources/empty.zip create mode 100644 connector/rest/src/test/resources/ivass-open-data-malformed.csv create mode 100644 connector/rest/src/test/resources/ivass-open-data.csv create mode 100644 connector/rest/src/test/resources/one_file.zip diff --git a/connector-api/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalException.java b/connector-api/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalException.java index c29c6691..824b6bb5 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalException.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalException.java @@ -10,4 +10,8 @@ public InternalException(){ super(); } + public InternalException(String message){ + super(message); + } + } diff --git a/connector/rest/pom.xml b/connector/rest/pom.xml index 78c4dd49..61dab333 100644 --- a/connector/rest/pom.xml +++ b/connector/rest/pom.xml @@ -58,5 +58,14 @@ jackson-dataformat-xml 2.14.1 + + org.springframework + spring-web + + + org.apache.httpcomponents + httpclient + 4.5.14 + diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandler.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandler.java new file mode 100644 index 00000000..d60ecb69 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandler.java @@ -0,0 +1,30 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.decoder; + +import it.pagopa.selfcare.party.registry_proxy.connector.exception.InternalException; +import it.pagopa.selfcare.party.registry_proxy.connector.exception.InvalidRequestException; +import it.pagopa.selfcare.party.registry_proxy.connector.exception.ResourceNotFoundException; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.ResponseErrorHandler; + +import java.io.IOException; + +@Configuration +public class RestTemplateErrorHandler implements ResponseErrorHandler { + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + return response.getStatusCode().isError(); + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + switch (response.getStatusCode()) { + case BAD_REQUEST: + throw new InvalidRequestException(response.getStatusText()); + case NOT_FOUND: + throw new ResourceNotFoundException(response.getStatusText()); + default: + throw new InternalException(response.getStatusText()); + } + } +} diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptor.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptor.java new file mode 100644 index 00000000..a38b42c3 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptor.java @@ -0,0 +1,29 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.interceptor; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; + +import java.io.IOException; + + +@Slf4j +@Component +public class IvassInterceptor implements ClientHttpRequestInterceptor { + @Override + @NonNull + public ClientHttpResponse intercept(@NonNull HttpRequest request, @NonNull byte[] body, @NonNull ClientHttpRequestExecution execution) throws IOException { + log.info("Request: " + request.getURI()); + log.info("Headers: " + request.getHeaders()); + log.info("Method: " + request.getMethod()); + ClientHttpResponse response = execution.execute(request, body); + log.info("Response Status: " + response.getStatusCode()); + log.info("Response Headers: " + response.getHeaders()); + return response; + } +} + diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/model/IvassDataTemplate.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/model/IvassDataTemplate.java new file mode 100644 index 00000000..74e35f03 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/model/IvassDataTemplate.java @@ -0,0 +1,36 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.model; + +import com.opencsv.bean.CsvBindByName; +import it.pagopa.selfcare.party.registry_proxy.connector.model.InsuranceCompany; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(of = "originId") +public class IvassDataTemplate implements InsuranceCompany { + + @CsvBindByName(column = "CODICE_IVASS") + private String originId; + @CsvBindByName(column = "CODICE_FISCALE") + private String taxCode; + @CsvBindByName(column = "DENOMINAZIONE_IMPRESA") + private String description; + @CsvBindByName(column = "PEC") + private String digitalAddress; + @CsvBindByName(column = "TIPO_LAVORO") + private String workType; + @CsvBindByName(column = "TIPO_ALBO") + private String registerType; + @CsvBindByName(column = "INDIRIZZO_SEDE_LEGALE_RAPPRESENTANZA_IN_ITALIA") + private String address; + + public String getTaxCode() { + if(!StringUtils.isBlank(this.taxCode) && this.taxCode.length() < 11) { + return StringUtils.leftPad(this.taxCode, 11, "0"); + } + return this.taxCode.trim(); + } +} \ No newline at end of file diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java new file mode 100644 index 00000000..cf353c2a --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -0,0 +1,67 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.utils; + +import com.opencsv.bean.CsvToBean; +import com.opencsv.bean.CsvToBeanBuilder; +import it.pagopa.selfcare.party.registry_proxy.connector.model.InsuranceCompany; +import it.pagopa.selfcare.party.registry_proxy.connector.rest.model.IvassDataTemplate; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.zip.ZipInputStream; + +@Slf4j +@Service +public class IvassUtils { + + public byte[] extractSingleFileFromZip(byte[] zipBytes) { + try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); + ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { + + if (zipInputStream.getNextEntry() != null) { + return toByteArray(zipInputStream); + } else { + throw new IOException("No entries found in the zip file"); + } + } catch (IOException e) { + log.debug("Error extracting file from zip", e); + return new byte[0]; + } + } + + private static byte[] toByteArray(ZipInputStream zipInputStream) throws IOException { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int length; + while ((length = zipInputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, length); + } + return byteArrayOutputStream.toByteArray(); + } + } + + public List readCsv(byte[] csv) { + List companies = new ArrayList<>(); + try (Reader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(csv)))) { + CsvToBean csvToBean = new CsvToBeanBuilder(reader) + .withType(IvassDataTemplate.class) + .withSeparator(';') + .build(); + companies = csvToBean.parse(); + } catch (Exception e) { + log.error("Impossible to acquire data for IVASS. Error: {}", e.getMessage(), e); + } + return new ArrayList<>(companies); + } + + public byte[] manageUTF8BOM(byte[] csv) { + // Check if the csv has the UTF-8 BOM and remove it + if (csv.length > 3 && csv[0] == (byte) 0xEF && csv[1] == (byte) 0xBB && csv[2] == (byte) 0xBF){ + csv = Arrays.copyOfRange(csv, 3, csv.length); + } + return csv; + } +} diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java new file mode 100644 index 00000000..198875c3 --- /dev/null +++ b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java @@ -0,0 +1,102 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.utils; + +import it.pagopa.selfcare.party.registry_proxy.connector.model.InsuranceCompany; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class IvassUtilsTest { + + @InjectMocks + private IvassUtils ivassUtil; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void extractSingleFileFromZip_shouldReturnByteArray_whenZipContainsSingleFile() throws IOException { + ClassPathResource resource = new ClassPathResource("one_file.zip"); + byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); + + byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + + assertNotNull(result); + assertTrue(result.length > 0); + } + + @Test + public void extractSingleFileFromZip_shouldReturnEmptyByteArray_whenZipIsEmpty() throws IOException { + ClassPathResource resource = new ClassPathResource("empty.zip"); + byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); + + byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + + assertNotNull(result); + assertEquals(0, result.length); + } + + @Test + public void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOException { + ClassPathResource resource = new ClassPathResource("ivass-open-data.csv"); + byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); + + List result = ivassUtil.readCsv(csvBytes); + + // Assert that the result is not null and has the expected size + assertNotNull(result); + assertEquals(2, result.size()); + } + + @Test + public void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { + byte[] csvBytes = new byte[0]; + + List result = ivassUtil.readCsv(csvBytes); + + // Assert that the result is not null and is empty + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException { + ClassPathResource resource = new ClassPathResource("ivass-open-data-malformed.csv"); + byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); + + List result = ivassUtil.readCsv(csvBytes); + + // Assert that the result is not null and is empty + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { + byte[] csvWithBOM = {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'a', 'b', 'c'}; + byte[] expectedCsv = {'a', 'b', 'c'}; + + byte[] result = ivassUtil.manageUTF8BOM(csvWithBOM); + + assertArrayEquals(expectedCsv, result); + } + + @Test + public void manageUTF8BOM_shouldReturnSameArray_whenBOMNotPresent() { + byte[] csvWithoutBOM = {'a', 'b', 'c'}; + byte[] expectedCsv = {'a', 'b', 'c'}; + + byte[] result = ivassUtil.manageUTF8BOM(csvWithoutBOM); + + assertArrayEquals(expectedCsv, result); + } + +} \ No newline at end of file diff --git a/connector/rest/src/test/resources/empty.zip b/connector/rest/src/test/resources/empty.zip new file mode 100644 index 0000000000000000000000000000000000000000..15cb0ecb3e219d1701294bfdf0fe3f5cb5d208e7 GIT binary patch literal 22 NcmWIWW@Tf*000g10H*)| literal 0 HcmV?d00001 diff --git a/connector/rest/src/test/resources/ivass-open-data-malformed.csv b/connector/rest/src/test/resources/ivass-open-data-malformed.csv new file mode 100644 index 00000000..5466a9c0 --- /dev/null +++ b/connector/rest/src/test/resources/ivass-open-data-malformed.csv @@ -0,0 +1,2 @@ +CODICE_IVASS;TIPO_ALBO;DATA_ISCRIZIONE_ALBO_ELENCO;DATA_CANCELLAZIONE_ALBO_ELENCO;DENOMINAZIONE_IMPRESA;CODICE_FISCALE;CLASSIFICAZIONE;INDIRIZZO_SEDE_LEGALE_RAPPRESENTANZA_IN_ITALIA;INDIRIZZO_DIREZIONE_GENERALE;INDIRIZZO_CASA_MADRE;TIPO_LAVORO;PEC +TEST1;;9999-12-31;FIRST INSURANCE;00000000001;IMPRESA SEE CHE OPERA IN STABILIMENTO;VIA TEST, 1 00000 ROMA;;;DANNI;test@pec.it diff --git a/connector/rest/src/test/resources/ivass-open-data.csv b/connector/rest/src/test/resources/ivass-open-data.csv new file mode 100644 index 00000000..75cd04eb --- /dev/null +++ b/connector/rest/src/test/resources/ivass-open-data.csv @@ -0,0 +1,3 @@ +CODICE_IVASS;TIPO_ALBO;DATA_ISCRIZIONE_ALBO_ELENCO;DATA_CANCELLAZIONE_ALBO_ELENCO;DENOMINAZIONE_IMPRESA;CODICE_FISCALE;CLASSIFICAZIONE;INDIRIZZO_SEDE_LEGALE_RAPPRESENTANZA_IN_ITALIA;INDIRIZZO_DIREZIONE_GENERALE;INDIRIZZO_CASA_MADRE;TIPO_LAVORO;PEC +TEST1;Elenco I - imprese di assicurazione con sede legale in un altro Stato membro ammesse ad operare in Italia in regime di stabilimento;2020-12-02;9999-12-31;FIRST INSURANCE;00000000001;IMPRESA SEE CHE OPERA IN STABILIMENTO;VIA TEST, 1 00000 ROMA;;;DANNI;test@pec.it +TEST2;Elenco I - imprese di assicurazione con sede legale in un altro Stato membro ammesse ad operare in Italia in regime di stabilimento;2020-06-10;9999-12-31;SECOND INSURANCE;00000000002;IMPRESA SEE CHE OPERA IN STABILIMENTO;VIA TEST, 2 00000 MILANO;;;DANNI;test2@pec.it diff --git a/connector/rest/src/test/resources/one_file.zip b/connector/rest/src/test/resources/one_file.zip new file mode 100644 index 0000000000000000000000000000000000000000..52c568e57a76bd591959dee41c439fe12c0ace28 GIT binary patch literal 159 zcmWIWW@h1H00EWq-w_A1Q$BG5*&xgT#3iZ4C3+ Date: Fri, 23 Aug 2024 13:03:35 +0200 Subject: [PATCH 2/7] SELC-4840 feat: fix sonar --- .../exception/InternalExceptionTest.java | 15 +++++++++++++++ .../connector/rest/utils/IvassUtils.java | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/connector-api/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalExceptionTest.java b/connector-api/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalExceptionTest.java index cb2007b4..0e841421 100644 --- a/connector-api/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalExceptionTest.java +++ b/connector-api/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/exception/InternalExceptionTest.java @@ -25,5 +25,20 @@ void testConstructor() { assertNull(cause.getMessage()); assertSame(suppressed, cause.getSuppressed()); } + + @Test + void constructorWithMessage() { + String message = "Error message"; + InternalException exception = new InternalException(message); + assertEquals(message, exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + void constructorWithMessage_nullMessage() { + InternalException exception = new InternalException((String) null); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } } diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index cf353c2a..7357005a 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -33,12 +33,23 @@ public byte[] extractSingleFileFromZip(byte[] zipBytes) { } private static byte[] toByteArray(ZipInputStream zipInputStream) throws IOException { + int totalSizeEntry = 0; + int THRESHOLD_SIZE = 100000000; // 100 MB + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int length; while ((length = zipInputStream.read(buffer)) != -1) { + totalSizeEntry += length; byteArrayOutputStream.write(buffer, 0, length); } + + // Check if the extracted file size exceeds the maximum allowed limit (security reasons) + if(totalSizeEntry > THRESHOLD_SIZE) { + log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); + return new byte[0]; + } + return byteArrayOutputStream.toByteArray(); } } From 68196e24bc2438120b7a48f0be3355e7f8bbf107 Mon Sep 17 00:00:00 2001 From: empassaro Date: Fri, 23 Aug 2024 13:21:00 +0200 Subject: [PATCH 3/7] SELC-4840 feat: increased coverage --- .../connector/rest/utils/IvassUtils.java | 3 +- .../decoder/RestTemplateErrorHandlerTest.java | 63 +++++++++++++++++++ .../interceptor/IvassInterceptorTest.java | 60 ++++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandlerTest.java create mode 100644 connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptorTest.java diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index 7357005a..7123bf44 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -19,8 +19,7 @@ public class IvassUtils { public byte[] extractSingleFileFromZip(byte[] zipBytes) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); - ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { - + ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { if (zipInputStream.getNextEntry() != null) { return toByteArray(zipInputStream); } else { diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandlerTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandlerTest.java new file mode 100644 index 00000000..793199de --- /dev/null +++ b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/decoder/RestTemplateErrorHandlerTest.java @@ -0,0 +1,63 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.decoder; + +import it.pagopa.selfcare.party.registry_proxy.connector.exception.InternalException; +import it.pagopa.selfcare.party.registry_proxy.connector.exception.InvalidRequestException; +import it.pagopa.selfcare.party.registry_proxy.connector.exception.ResourceNotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + +class RestTemplateErrorHandlerTest { + @Mock + private ClientHttpResponse response; + + @InjectMocks + private RestTemplateErrorHandler errorHandler; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void hasError_shouldReturnTrue_whenResponseIsError() throws IOException { + when(response.getStatusCode()).thenReturn(HttpStatus.BAD_REQUEST); + assertTrue(errorHandler.hasError(response)); + } + + @Test + void hasError_shouldReturnFalse_whenResponseIsNotError() throws IOException { + when(response.getStatusCode()).thenReturn(HttpStatus.OK); + assertFalse(errorHandler.hasError(response)); + } + + @Test + void handleError_shouldThrowInvalidRequestException_whenStatusIsBadRequest() throws IOException { + when(response.getStatusCode()).thenReturn(HttpStatus.BAD_REQUEST); + when(response.getStatusText()).thenReturn("Bad Request"); + assertThrows(InvalidRequestException.class, () -> errorHandler.handleError(response)); + } + + @Test + void handleError_shouldThrowResourceNotFoundException_whenStatusIsNotFound() throws IOException { + when(response.getStatusCode()).thenReturn(HttpStatus.NOT_FOUND); + when(response.getStatusText()).thenReturn("Not Found"); + assertThrows(ResourceNotFoundException.class, () -> errorHandler.handleError(response)); + } + + @Test + void handleError_shouldThrowInternalException_whenStatusIsOtherError() throws IOException { + when(response.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR); + when(response.getStatusText()).thenReturn("Internal Server Error"); + assertThrows(InternalException.class, () -> errorHandler.handleError(response)); + } +} \ No newline at end of file diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptorTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptorTest.java new file mode 100644 index 00000000..3cdb1c26 --- /dev/null +++ b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/interceptor/IvassInterceptorTest.java @@ -0,0 +1,60 @@ +package it.pagopa.selfcare.party.registry_proxy.connector.rest.interceptor; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; + +class IvassInterceptorTest { + @Mock + private HttpRequest request; + + @Mock + private ClientHttpRequestExecution execution; + + @Mock + private ClientHttpResponse response; + + @InjectMocks + private IvassInterceptor ivassInterceptor; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void intercept_shouldLogRequestAndResponseDetails() throws IOException { + byte[] body = new byte[]{}; + when(execution.execute(request, body)).thenReturn(response); + when(response.getStatusCode()).thenReturn(HttpStatus.OK); + + ClientHttpResponse result = ivassInterceptor.intercept(request, body, execution); + + assertEquals(response, result); + verify(request, times(1)).getURI(); + verify(request, times(1)).getHeaders(); + verify(request, times(1)).getMethod(); + verify(response, times(1)).getStatusCode(); + verify(response, times(1)).getHeaders(); + } + + @Test + void intercept_shouldHandleIOException() throws IOException { + byte[] body = new byte[]{}; + when(execution.execute(request, body)).thenThrow(new IOException("Test exception")); + + assertThrows(IOException.class, () -> ivassInterceptor.intercept(request, body, execution)); + } +} \ No newline at end of file From de104f52bb9cfc1f2f7793cbbc011e71e6a3555b Mon Sep 17 00:00:00 2001 From: empassaro Date: Mon, 26 Aug 2024 20:58:23 +0200 Subject: [PATCH 4/7] SELC-4840 fix: check compression ratio when extracting file from zip (sonar) --- .../connector/rest/utils/IvassUtils.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index 7123bf44..0ad44efe 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @Slf4j @@ -20,8 +21,10 @@ public class IvassUtils { public byte[] extractSingleFileFromZip(byte[] zipBytes) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { - if (zipInputStream.getNextEntry() != null) { - return toByteArray(zipInputStream); + ZipEntry entry = zipInputStream.getNextEntry(); + + if (entry != null) { + return toByteArray(entry, zipInputStream); } else { throw new IOException("No entries found in the zip file"); } @@ -31,22 +34,32 @@ public byte[] extractSingleFileFromZip(byte[] zipBytes) { } } - private static byte[] toByteArray(ZipInputStream zipInputStream) throws IOException { + private static byte[] toByteArray(ZipEntry zipEntry, ZipInputStream zipInputStream) throws IOException { int totalSizeEntry = 0; int THRESHOLD_SIZE = 100000000; // 100 MB + double THRESHOLD_RATIO = 10; // 10 times the compressed size + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int length; while ((length = zipInputStream.read(buffer)) != -1) { totalSizeEntry += length; - byteArrayOutputStream.write(buffer, 0, length); - } - // Check if the extracted file size exceeds the maximum allowed limit (security reasons) - if(totalSizeEntry > THRESHOLD_SIZE) { - log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); - return new byte[0]; + // Check the compression ratio of the extracted file (security reasons) + double compressionRatio = (double) totalSizeEntry / zipEntry.getCompressedSize(); + if(compressionRatio > THRESHOLD_RATIO) { + log.error("Compression ratio exceeds the maximum allowed limit of " + THRESHOLD_RATIO); + return new byte[0]; + } + + // Check if the extracted file size exceeds the maximum allowed limit (security reasons) + if(totalSizeEntry > THRESHOLD_SIZE) { + log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); + return new byte[0]; + } + + byteArrayOutputStream.write(buffer, 0, length); } return byteArrayOutputStream.toByteArray(); From 6540f107bf10a9aa763a5e07e442539d135a4eb1 Mon Sep 17 00:00:00 2001 From: empassaro Date: Tue, 27 Aug 2024 14:49:14 +0200 Subject: [PATCH 5/7] SELC-4840 fix: sonar --- .../connector/rest/utils/IvassUtils.java | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index 0ad44efe..3ed651a5 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -24,45 +24,39 @@ public byte[] extractSingleFileFromZip(byte[] zipBytes) { ZipEntry entry = zipInputStream.getNextEntry(); if (entry != null) { - return toByteArray(entry, zipInputStream); - } else { - throw new IOException("No entries found in the zip file"); - } - } catch (IOException e) { - log.debug("Error extracting file from zip", e); - return new byte[0]; - } - } + int totalSizeEntry = 0; + int THRESHOLD_SIZE = 100000000; // 100 MB + double THRESHOLD_RATIO = 10; // 10 times the compressed size - private static byte[] toByteArray(ZipEntry zipEntry, ZipInputStream zipInputStream) throws IOException { - int totalSizeEntry = 0; - int THRESHOLD_SIZE = 100000000; // 100 MB - double THRESHOLD_RATIO = 10; // 10 times the compressed size + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int length; + while ((length = zipInputStream.read(buffer)) != -1) { + totalSizeEntry += length; + // Check the compression ratio of the extracted file (security reasons) + double compressionRatio = (double) totalSizeEntry / entry.getCompressedSize(); + if(compressionRatio > THRESHOLD_RATIO) { + log.error("Compression ratio exceeds the maximum allowed limit of " + THRESHOLD_RATIO); + return new byte[0]; + } - try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { - byte[] buffer = new byte[1024]; - int length; - while ((length = zipInputStream.read(buffer)) != -1) { - totalSizeEntry += length; + // Check if the extracted file size exceeds the maximum allowed limit (security reasons) + if(totalSizeEntry > THRESHOLD_SIZE) { + log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); + return new byte[0]; + } - // Check the compression ratio of the extracted file (security reasons) - double compressionRatio = (double) totalSizeEntry / zipEntry.getCompressedSize(); - if(compressionRatio > THRESHOLD_RATIO) { - log.error("Compression ratio exceeds the maximum allowed limit of " + THRESHOLD_RATIO); - return new byte[0]; + byteArrayOutputStream.write(buffer, 0, length); + } + return byteArrayOutputStream.toByteArray(); } - - // Check if the extracted file size exceeds the maximum allowed limit (security reasons) - if(totalSizeEntry > THRESHOLD_SIZE) { - log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); - return new byte[0]; - } - - byteArrayOutputStream.write(buffer, 0, length); + } else { + throw new IOException("No entries found in the zip file"); } - - return byteArrayOutputStream.toByteArray(); + } catch (IOException e) { + log.debug("Error extracting file from zip", e); + return new byte[0]; } } From 96e834bb923877f1eb5d563c621ceadfd4165f00 Mon Sep 17 00:00:00 2001 From: empassaro Date: Tue, 27 Aug 2024 15:00:13 +0200 Subject: [PATCH 6/7] SELC-4840 fix: sonar issues --- .../connector/rest/utils/IvassUtils.java | 14 ++++++------- .../connector/rest/utils/IvassUtilsTest.java | 20 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index 3ed651a5..77e17bf9 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -18,15 +18,15 @@ @Service public class IvassUtils { - public byte[] extractSingleFileFromZip(byte[] zipBytes) { + public byte[] extractFirstEntryByteArrayFromZip(byte[] zipBytes) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { ZipEntry entry = zipInputStream.getNextEntry(); if (entry != null) { int totalSizeEntry = 0; - int THRESHOLD_SIZE = 100000000; // 100 MB - double THRESHOLD_RATIO = 10; // 10 times the compressed size + int thresholdSize = 100000000; // 100 MB + double thresholdRatio = 10; // 10 times the compressed size try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; @@ -36,14 +36,14 @@ public byte[] extractSingleFileFromZip(byte[] zipBytes) { // Check the compression ratio of the extracted file (security reasons) double compressionRatio = (double) totalSizeEntry / entry.getCompressedSize(); - if(compressionRatio > THRESHOLD_RATIO) { - log.error("Compression ratio exceeds the maximum allowed limit of " + THRESHOLD_RATIO); + if(compressionRatio > thresholdRatio) { + log.error("Compression ratio exceeds the maximum allowed limit of " + thresholdRatio); return new byte[0]; } // Check if the extracted file size exceeds the maximum allowed limit (security reasons) - if(totalSizeEntry > THRESHOLD_SIZE) { - log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); + if(totalSizeEntry > thresholdSize) { + log.error("Extracted file size exceeds the maximum allowed limit of " + thresholdSize + " bytes"); return new byte[0]; } diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java index 198875c3..b3e1fc8e 100644 --- a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java +++ b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java @@ -18,34 +18,34 @@ public class IvassUtilsTest { private IvassUtils ivassUtil; @BeforeEach - public void setup() { + void setup() { MockitoAnnotations.openMocks(this); } @Test - public void extractSingleFileFromZip_shouldReturnByteArray_whenZipContainsSingleFile() throws IOException { + void extractSingleFileFromZip_shouldReturnByteArray_whenZipContainsSingleFile() throws IOException { ClassPathResource resource = new ClassPathResource("one_file.zip"); byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); - byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + byte[] result = ivassUtil.extractFirstEntryByteArrayFromZip(zipBytes); assertNotNull(result); assertTrue(result.length > 0); } @Test - public void extractSingleFileFromZip_shouldReturnEmptyByteArray_whenZipIsEmpty() throws IOException { + void extractSingleFileFromZip_shouldReturnEmptyByteArray_whenZipIsEmpty() throws IOException { ClassPathResource resource = new ClassPathResource("empty.zip"); byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); - byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + byte[] result = ivassUtil.extractFirstEntryByteArrayFromZip(zipBytes); assertNotNull(result); assertEquals(0, result.length); } @Test - public void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOException { + void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOException { ClassPathResource resource = new ClassPathResource("ivass-open-data.csv"); byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); @@ -57,7 +57,7 @@ public void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOExcept } @Test - public void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { + void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { byte[] csvBytes = new byte[0]; List result = ivassUtil.readCsv(csvBytes); @@ -68,7 +68,7 @@ public void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { } @Test - public void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException { + void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException { ClassPathResource resource = new ClassPathResource("ivass-open-data-malformed.csv"); byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); @@ -80,7 +80,7 @@ public void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException } @Test - public void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { + void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { byte[] csvWithBOM = {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'a', 'b', 'c'}; byte[] expectedCsv = {'a', 'b', 'c'}; @@ -90,7 +90,7 @@ public void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { } @Test - public void manageUTF8BOM_shouldReturnSameArray_whenBOMNotPresent() { + void manageUTF8BOM_shouldReturnSameArray_whenBOMNotPresent() { byte[] csvWithoutBOM = {'a', 'b', 'c'}; byte[] expectedCsv = {'a', 'b', 'c'}; From 5a7fde57233674acccfdfa9edc46255d1e2a401d Mon Sep 17 00:00:00 2001 From: empassaro Date: Tue, 27 Aug 2024 15:00:13 +0200 Subject: [PATCH 7/7] SELC-4840 fix: sonar issues --- .../connector/rest/utils/IvassUtils.java | 14 ++++++------ .../connector/rest/utils/IvassUtilsTest.java | 22 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java index 3ed651a5..77e17bf9 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtils.java @@ -18,15 +18,15 @@ @Service public class IvassUtils { - public byte[] extractSingleFileFromZip(byte[] zipBytes) { + public byte[] extractFirstEntryByteArrayFromZip(byte[] zipBytes) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) { ZipEntry entry = zipInputStream.getNextEntry(); if (entry != null) { int totalSizeEntry = 0; - int THRESHOLD_SIZE = 100000000; // 100 MB - double THRESHOLD_RATIO = 10; // 10 times the compressed size + int thresholdSize = 100000000; // 100 MB + double thresholdRatio = 10; // 10 times the compressed size try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; @@ -36,14 +36,14 @@ public byte[] extractSingleFileFromZip(byte[] zipBytes) { // Check the compression ratio of the extracted file (security reasons) double compressionRatio = (double) totalSizeEntry / entry.getCompressedSize(); - if(compressionRatio > THRESHOLD_RATIO) { - log.error("Compression ratio exceeds the maximum allowed limit of " + THRESHOLD_RATIO); + if(compressionRatio > thresholdRatio) { + log.error("Compression ratio exceeds the maximum allowed limit of " + thresholdRatio); return new byte[0]; } // Check if the extracted file size exceeds the maximum allowed limit (security reasons) - if(totalSizeEntry > THRESHOLD_SIZE) { - log.error("Extracted file size exceeds the maximum allowed limit of " + THRESHOLD_SIZE + " bytes"); + if(totalSizeEntry > thresholdSize) { + log.error("Extracted file size exceeds the maximum allowed limit of " + thresholdSize + " bytes"); return new byte[0]; } diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java index 198875c3..53ab72a3 100644 --- a/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java +++ b/connector/rest/src/test/java/it/pagopa/selfcare/party/registry_proxy/connector/rest/utils/IvassUtilsTest.java @@ -12,40 +12,40 @@ import static org.junit.jupiter.api.Assertions.*; -public class IvassUtilsTest { +class IvassUtilsTest { @InjectMocks private IvassUtils ivassUtil; @BeforeEach - public void setup() { + void setup() { MockitoAnnotations.openMocks(this); } @Test - public void extractSingleFileFromZip_shouldReturnByteArray_whenZipContainsSingleFile() throws IOException { + void extractSingleFileFromZip_shouldReturnByteArray_whenZipContainsSingleFile() throws IOException { ClassPathResource resource = new ClassPathResource("one_file.zip"); byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); - byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + byte[] result = ivassUtil.extractFirstEntryByteArrayFromZip(zipBytes); assertNotNull(result); assertTrue(result.length > 0); } @Test - public void extractSingleFileFromZip_shouldReturnEmptyByteArray_whenZipIsEmpty() throws IOException { + void extractSingleFileFromZip_shouldReturnEmptyByteArray_whenZipIsEmpty() throws IOException { ClassPathResource resource = new ClassPathResource("empty.zip"); byte[] zipBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); - byte[] result = ivassUtil.extractSingleFileFromZip(zipBytes); + byte[] result = ivassUtil.extractFirstEntryByteArrayFromZip(zipBytes); assertNotNull(result); assertEquals(0, result.length); } @Test - public void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOException { + void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOException { ClassPathResource resource = new ClassPathResource("ivass-open-data.csv"); byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); @@ -57,7 +57,7 @@ public void readCsv_shouldReturnListOfCompanies_whenCsvIsValid() throws IOExcept } @Test - public void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { + void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { byte[] csvBytes = new byte[0]; List result = ivassUtil.readCsv(csvBytes); @@ -68,7 +68,7 @@ public void readCsv_shouldReturnEmptyList_whenCsvIsEmpty() { } @Test - public void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException { + void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException { ClassPathResource resource = new ClassPathResource("ivass-open-data-malformed.csv"); byte[] csvBytes = java.nio.file.Files.readAllBytes(resource.getFile().toPath()); @@ -80,7 +80,7 @@ public void readCsv_shouldReturnEmptyList_whenCsvIsInvalid() throws IOException } @Test - public void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { + void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { byte[] csvWithBOM = {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'a', 'b', 'c'}; byte[] expectedCsv = {'a', 'b', 'c'}; @@ -90,7 +90,7 @@ public void manageUTF8BOM_shouldRemoveBOM_whenBOMPresent() { } @Test - public void manageUTF8BOM_shouldReturnSameArray_whenBOMNotPresent() { + void manageUTF8BOM_shouldReturnSameArray_whenBOMNotPresent() { byte[] csvWithoutBOM = {'a', 'b', 'c'}; byte[] expectedCsv = {'a', 'b', 'c'};