Feature/fix sonar warnings (#1226)
* Fixed sonar warnings - "Cognitive Complexity" - "Do not use replaceAll when not using a regex" - java:S5869 - Character classes in regular expressions should not contain the same character twice - Improved bad name - Typos - reduced code duplications - Replaced hand-made wait-utility with Awaitility - Log messages - Duplicate code - Typos - Removed Thread.sleep, instead relaxed check condition - Removed use of deprecated API - Removed use of deprecated API - Added supress-warnings as I do not see a better way to write the tests - Removed Thread.sleep / redundant functionality to Awaitility - Fixed other warnings (use isZero, isEmpty, hasToString) - Removed/Reduced duplicate code - Added generics - Fixed asserts - removed: field.setAccessible(true) actually should not be needed for public static fields! - Too long constructor passes arguments in wrong order - how surprisingly... - Clean-up use of varargs arguments - Fixed regex - Fixed typos and other minor stuff - Making public constructors protected in abstract classes - Swapped expected and asserted argument - volatile not enough for syncing threads - volatile not enough for syncing threads - out-commented code - Made regex not-greedy, added tests for verification - Avoid exposure of thread-local member var Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixed Sonar warnings * License header fix Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * License header fix #2 Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing review findings Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing tests - Fixed '&' usage in javadoc and typos - Fixing some warnings Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io>
This commit is contained in:
@@ -74,9 +74,9 @@ public class RestConfiguration {
|
||||
* filter in the filter chain
|
||||
*/
|
||||
@Bean
|
||||
FilterRegistrationBean eTagFilter() {
|
||||
FilterRegistrationBean<ExcludePathAwareShallowETagFilter> eTagFilter() {
|
||||
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
final FilterRegistrationBean<ExcludePathAwareShallowETagFilter> filterRegBean = new FilterRegistrationBean<>();
|
||||
// Exclude the URLs for downloading artifacts, so no eTag is generated
|
||||
// in the ShallowEtagHeaderFilter, just using the SH1 hash of the
|
||||
// artifact itself as 'ETag', because otherwise the file will be copied
|
||||
|
||||
@@ -151,7 +151,7 @@ public final class FileStreamingUtil {
|
||||
LOG.debug("range header for filename ({}) is: {}", filename, range);
|
||||
|
||||
// Range header matches"bytes=n-n,n-n,n-n..."
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*+$")) {
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
||||
LOG.debug("range header for filename ({}) is not satisfiable: ", filename);
|
||||
return new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Management API")
|
||||
@Story("File streaming")
|
||||
class FileStreamingUtilTest {
|
||||
private final static String CONTENT = "This is some very long string which is intended to test";
|
||||
private final static byte[] CONTENT_BYTES = CONTENT.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private static final DbArtifact TEST_ARTIFACT = new DbArtifact() {
|
||||
|
||||
@Override
|
||||
public String getArtifactId() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbArtifactHash getHashes() {
|
||||
return new DbArtifactHash("sha1-111", "md5-123", "sha256-123");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return CONTENT_BYTES.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFileInputStream() {
|
||||
return new ByteArrayInputStream(CONTENT_BYTES);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void shouldProcessRangeHeaderForMultipartRequests() throws IOException {
|
||||
final HttpServletResponse servletResponse = Mockito.mock(HttpServletResponse.class);
|
||||
final ServletOutputStream outputStream = Mockito.mock(ServletOutputStream.class);
|
||||
|
||||
Mockito.when(servletResponse.getOutputStream()).thenReturn(outputStream);
|
||||
final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10,9-15,16-");
|
||||
long lastModified = System.currentTimeMillis();
|
||||
|
||||
final ResponseEntity<InputStream> responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT,
|
||||
"test.file", lastModified, servletResponse, servletRequest, null);
|
||||
|
||||
assertThat(responseEntity).isNotNull();
|
||||
verify(servletResponse).setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified);
|
||||
final ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
|
||||
final ArgumentCaptor<Integer> lenCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
verify(outputStream).print(stringCaptor.capture());
|
||||
assertThat(stringCaptor.getValue()).contains("--THIS_STRING_SEPARATES_MULTIPART--");
|
||||
verify(outputStream, times(3)).write(any(), anyInt(), lenCaptor.capture());
|
||||
assertThat(lenCaptor.getAllValues()).containsExactly(11, 7, 39); // Range lengths
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldValidateRangeHeaderForMultipartRequests() throws IOException {
|
||||
long lastModified = System.currentTimeMillis();
|
||||
final HttpServletResponse servletResponse = Mockito.mock(HttpServletResponse.class);
|
||||
final ServletOutputStream outputStream = Mockito.mock(ServletOutputStream.class);
|
||||
Mockito.when(servletResponse.getOutputStream()).thenReturn(outputStream);
|
||||
|
||||
final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10***,9-15,16-");
|
||||
|
||||
final ResponseEntity<InputStream> responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT,
|
||||
"test.file", lastModified, servletResponse, servletRequest, null);
|
||||
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
verify(outputStream, times(0)).print(anyString());
|
||||
verify(outputStream, times(0)).write(any(), anyInt(), anyInt());
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,24 +42,21 @@ public class SortUtilityTest {
|
||||
@Description("Ascending sorting based on name.")
|
||||
public void parseSortParam1() {
|
||||
final List<Order> parse = SortUtility.parse(TargetFields.class, SORT_PARAM_1);
|
||||
assertThat(1).as("Count of parsing parameter").isEqualTo(parse.size());
|
||||
assertThat(parse).as("Count of parsing parameter").hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ascending sorting based on name and descending sorting based on description.")
|
||||
public void parseSortParam2() {
|
||||
final List<Order> parse = SortUtility.parse(TargetFields.class, SORT_PARAM_2);
|
||||
assertThat(2).as("Count of parsing parameter").isEqualTo(parse.size());
|
||||
assertThat(parse).as("Count of parsing parameter").hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Sorting with wrong syntax leads to SortParameterSyntaxErrorException.")
|
||||
public void parseWrongSyntaxParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, SYNTAX_FAILURE_SORT_PARAM);
|
||||
fail("SortParameterSyntaxErrorException expected because of wrong syntax");
|
||||
} catch (final SortParameterSyntaxErrorException e) {
|
||||
}
|
||||
assertThrows(SortParameterSyntaxErrorException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, SYNTAX_FAILURE_SORT_PARAM));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,22 +69,14 @@ public class SortUtilityTest {
|
||||
@Test
|
||||
@Description("Sorting with unknown direction order leads to SortParameterUnsupportedDirectionException.")
|
||||
public void parseWrongDirectionParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, WRONG_DIRECTION_PARAM);
|
||||
fail("SortParameterUnsupportedDirectionException expected because of unknown direction order");
|
||||
} catch (final SortParameterUnsupportedDirectionException e) {
|
||||
}
|
||||
|
||||
assertThrows(SortParameterUnsupportedDirectionException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, WRONG_DIRECTION_PARAM));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Sorting with unknown field leads to SortParameterUnsupportedFieldException.")
|
||||
public void parseWrongFieldParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, WRONG_FIELD_PARAM);
|
||||
fail("SortParameterUnsupportedFieldException expected because of unknown field");
|
||||
} catch (final SortParameterUnsupportedFieldException e) {
|
||||
}
|
||||
|
||||
assertThrows(SortParameterUnsupportedFieldException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, WRONG_FIELD_PARAM));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user