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:
Peter Vigier
2022-01-31 21:59:46 +01:00
committed by GitHub
parent 5443b5df9c
commit 44a85f20eb
98 changed files with 2583 additions and 2702 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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));
}
}