diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java index 348e8dea4..4d313dd2c 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java @@ -91,7 +91,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost()); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage); - assertTrue(downloadAndUpdateRequest.getSoftwareModules().isEmpty()); + assertTrue("No softwaremmodule should be contained in the request", + downloadAndUpdateRequest.getSoftwareModules().isEmpty()); } @Test @@ -104,17 +105,22 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost()); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage); - assertEquals(3, downloadAndUpdateRequest.getSoftwareModules().size()); + assertEquals("Expecting a size of 3 software modules in the reuqest", 3, + downloadAndUpdateRequest.getSoftwareModules().size()); for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest .getSoftwareModules()) { - assertTrue(softwareModule.getArtifacts().isEmpty()); + assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty()); for (final SoftwareModule softwareModule2 : dsA.getModules()) { - assertNotNull(softwareModule.getModuleId()); + assertNotNull("Sofware module ID should be set", softwareModule.getModuleId()); if (!softwareModule.getModuleId().equals(softwareModule2.getId())) { continue; } - assertEquals(softwareModule.getModuleType(), softwareModule2.getType().getKey()); - assertEquals(softwareModule.getModuleVersion(), softwareModule2.getVersion()); + assertEquals( + "Software module type in event should be the same as the softwaremodule in the distribution set", + softwareModule.getModuleType(), softwareModule2.getType().getKey()); + assertEquals( + "Software module version in event should be the same as the softwaremodule in the distribution set", + softwareModule.getModuleVersion(), softwareModule2.getVersion()); } } } @@ -138,13 +144,14 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost()); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage); - assertEquals(3, downloadAndUpdateRequest.getSoftwareModules().size()); + assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3, + downloadAndUpdateRequest.getSoftwareModules().size()); for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest .getSoftwareModules()) { if (!softwareModule.getModuleId().equals(module.getId())) { continue; } - assertFalse(softwareModule.getArtifacts().isEmpty()); + assertFalse("The software module artifacts should not be empty", softwareModule.getArtifacts().isEmpty()); } } @@ -164,8 +171,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit private void assertCancelMessage(final Message sendMessage) { assertEventMessage(sendMessage); final Long actionId = convertMessage(sendMessage, Long.class); - assertEquals(actionId, Long.valueOf(1)); - assertEquals(EventTopic.CANCEL_DOWNLOAD, + assertEquals("Action ID should be 1", actionId, Long.valueOf(1)); + assertEquals("The topc in the message should be a CANCEL_DOWNLOAD value", EventTopic.CANCEL_DOWNLOAD, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC)); } @@ -174,8 +181,9 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit assertEventMessage(sendMessage); final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage, DownloadAndUpdateRequest.class); - assertEquals(downloadAndUpdateRequest.getActionId(), Long.valueOf(1)); - assertEquals(EventTopic.DOWNLOAD_AND_INSTALL, + assertEquals("The action ID of the downloadAndUpdateRequest event shuold be 1", + downloadAndUpdateRequest.getActionId(), Long.valueOf(1)); + assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC)); return downloadAndUpdateRequest; @@ -185,11 +193,14 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit * @param sendMessage */ private void assertEventMessage(final Message sendMessage) { - assertNotNull(sendMessage); + assertNotNull("The message should not be null", sendMessage); - assertEquals(CONTROLLER_ID, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID)); - assertEquals(MessageType.EVENT, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE)); - assertEquals(MessageProperties.CONTENT_TYPE_JSON, sendMessage.getMessageProperties().getContentType()); + assertEquals("The value of the message header THING_ID should be " + CONTROLLER_ID, CONTROLLER_ID, + sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID)); + assertEquals("The value of the message header TYPE should be EVENT", MessageType.EVENT, + sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE)); + assertEquals("The content type message should be " + MessageProperties.CONTENT_TYPE_JSON, + MessageProperties.CONTENT_TYPE_JSON, sendMessage.getMessageProperties().getContentType()); } protected Message createArgumentCapture(final String exchange) { diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ArtifactManagementTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ArtifactManagementTest.java index 5585aab95..2929110dd 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ArtifactManagementTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ArtifactManagementTest.java @@ -150,14 +150,14 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB { ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId()); - assertNotNull(result); + assertNotNull("The result of an external artifact should not be null", result); assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1); assertThat(result.getSoftwareModule().getId()).isEqualTo(sm.getId()); assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/{version}/"); assertThat(result.getExternalArtifactProvider()).isEqualTo(provider); result = artifactManagement.createExternalArtifact(provider, "/test", sm2.getId()); - assertNotNull(result); + assertNotNull("The newly created external artifact should not be null", result); assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(2); assertThat(result.getUrl()).isEqualTo("https://fhghdfjgh/test"); assertThat(result.getExternalArtifactProvider()).isEqualTo(provider); @@ -176,7 +176,7 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB { "https://fhghdfjgh", "/{version}/"); final ExternalArtifact result = artifactManagement.createExternalArtifact(provider, null, sm.getId()); - assertNotNull(result); + assertNotNull("The newly created external artifact should not be null", result); assertThat(externalArtifactRepository.findAll()).contains(result).hasSize(1); artifactManagement.deleteExternalArtifact(result.getId()); @@ -348,7 +348,7 @@ public class ArtifactManagementTest extends AbstractIntegrationTestWithMongoDB { final LocalArtifact result = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(), "file1", false); - assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random), + assertTrue("The stored binary matches the given binary", IOUtils.contentEquals(new ByteArrayInputStream(random), artifactManagement.loadLocalArtifactBinary(result).getFileInputStream())); } diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/SoftwareManagementTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/SoftwareManagementTest.java index dc9a654c7..49776e392 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/SoftwareManagementTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/SoftwareManagementTest.java @@ -159,10 +159,10 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { public void hardDeleteOfNotAssignedArtifact() { // [STEP1]: Create SoftwareModuleX with Artifacts - SoftwareModule unassignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2); - Iterator artifactsIt = unassignedModule.getArtifacts().iterator(); - Artifact artifact1 = artifactsIt.next(); - Artifact artifact2 = artifactsIt.next(); + final SoftwareModule unassignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2); + final Iterator artifactsIt = unassignedModule.getArtifacts().iterator(); + final Artifact artifact1 = artifactsIt.next(); + final Artifact artifact2 = artifactsIt.next(); // [STEP2]: Delete unassigned SoftwareModule softwareManagement.deleteSoftwareModule(unassignedModule); @@ -185,7 +185,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { public void softDeleteOfAssignedArtifact() { // Init DistributionSet - DistributionSet disSet = distributionSetManagement + final DistributionSet disSet = distributionSetManagement .createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null)); // [STEP1]: Create SoftwareModuleX with ArtifactX @@ -200,14 +200,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // [VERIFY EXPECTED RESULT]: // verify: assignedModule is marked as deleted assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId()); - assertTrue(assignedModule.isDeleted()); + assertTrue("The module should be flagged as deleted", assignedModule.isDeleted()); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareModuleRepository.findAll()).hasSize(1); // verify: binary data is deleted - Iterator artifactsIt = assignedModule.getArtifacts().iterator(); - Artifact artifact1 = artifactsIt.next(); - Artifact artifact2 = artifactsIt.next(); + final Iterator artifactsIt = assignedModule.getArtifacts().iterator(); + final Artifact artifact1 = artifactsIt.next(); + final Artifact artifact2 = artifactsIt.next(); assertArtfiactNull(artifact1, artifact2); // verify: artifact meta data is still available @@ -221,7 +221,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // Init target and DistributionSet final Target target = targetManagement.createTarget(new Target("test123")); - DistributionSet disSet = distributionSetManagement + final DistributionSet disSet = distributionSetManagement .createDistributionSet(new DistributionSet("ds1", "v1.0", "test ds", standardDsType, null)); // [STEP1]: Create SoftwareModuleX and include the new ArtifactX @@ -242,14 +242,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // [VERIFY EXPECTED RESULT]: // verify: assignedModule is marked as deleted assignedModule = softwareManagement.findSoftwareModuleById(assignedModule.getId()); - assertTrue(assignedModule.isDeleted()); + assertTrue("The found module should be flagged deleted", assignedModule.isDeleted()); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareModuleRepository.findAll()).hasSize(1); // verify: binary data is deleted - Iterator artifactsIt = assignedModule.getArtifacts().iterator(); - Artifact artifact1 = artifactsIt.next(); - Artifact artifact2 = artifactsIt.next(); + final Iterator artifactsIt = assignedModule.getArtifacts().iterator(); + final Artifact artifact1 = artifactsIt.next(); + final Artifact artifact2 = artifactsIt.next(); assertArtfiactNull(artifact1, artifact2); // verify: artifact meta data is still available @@ -265,7 +265,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { assertThat(operations.find(new Query())).hasSize(0); // Init artifact binary data, target and DistributionSets - byte[] source = RandomUtils.nextBytes(1024); + final byte[] source = RandomUtils.nextBytes(1024); // [STEP1]: Create SoftwareModuleX and add a new ArtifactX SoftwareModule moduleX = createSoftwareModuleWithArtifacts(osType, "modulex", "v1.0", 0); @@ -273,7 +273,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // [STEP2]: Create newArtifactX and add it to SoftwareModuleX artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false); moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId()); - Artifact artifactX = moduleX.getArtifacts().iterator().next(); + final Artifact artifactX = moduleX.getArtifacts().iterator().next(); // [STEP3]: Create SoftwareModuleY and add the same ArtifactX SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0); @@ -281,7 +281,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // [STEP4]: Assign the same ArtifactX to SoftwareModuleY artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false); moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId()); - Artifact artifactY = moduleY.getArtifacts().iterator().next(); + final Artifact artifactY = moduleY.getArtifacts().iterator().next(); // verify: that only one entry was created in mongoDB assertThat(operations.find(new Query())).hasSize(1); @@ -325,14 +325,14 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false); moduleX = softwareManagement.findSoftwareModuleWithDetails(moduleX.getId()); - Artifact artifactX = moduleX.getArtifacts().iterator().next(); + final Artifact artifactX = moduleX.getArtifacts().iterator().next(); // [STEP2]: Create SoftwareModuleY and add the same ArtifactX SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0); artifactManagement.createLocalArtifact(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", false); moduleY = softwareManagement.findSoftwareModuleWithDetails(moduleY.getId()); - Artifact artifactY = moduleY.getArtifacts().iterator().next(); + final Artifact artifactY = moduleY.getArtifacts().iterator().next(); // verify: that only one entry was created in mongoDB assertThat(operations.find(new Query())).hasSize(1); @@ -358,8 +358,8 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { // verify: SoftwareModuleX and SofwtareModule are marked as deleted assertThat(moduleX).isNotNull(); assertThat(moduleY).isNotNull(); - assertTrue(moduleX.isDeleted()); - assertTrue(moduleY.isDeleted()); + assertTrue("The module should be flagged deleted", moduleX.isDeleted()); + assertTrue("The module should be flagged deleted", moduleY.isDeleted()); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareModuleRepository.findAll()).hasSize(2); @@ -370,10 +370,10 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { assertThat(artifactRepository.findOne(artifactY.getId())).isNotNull(); } - private SoftwareModule createSoftwareModuleWithArtifacts(SoftwareModuleType type, String name, String version, - int numberArtifacts) { + private SoftwareModule createSoftwareModuleWithArtifacts(final SoftwareModuleType type, final String name, + final String version, final int numberArtifacts) { - long countSoftwareModule = softwareModuleRepository.count(); + final long countSoftwareModule = softwareModuleRepository.count(); // create SoftwareModule SoftwareModule softwareModule = softwareManagement @@ -388,7 +388,7 @@ public class SoftwareManagementTest extends AbstractIntegrationTestWithMongoDB { softwareModule = softwareManagement.findSoftwareModuleWithDetails(softwareModule.getId()); assertThat(softwareModuleRepository.findAll()).hasSize((int) countSoftwareModule + 1); - List artifacts = softwareModule.getArtifacts(); + final List artifacts = softwareModule.getArtifacts(); assertThat(artifacts).hasSize(numberArtifacts); if (numberArtifacts != 0) { diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLActionFieldsTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLActionFieldsTest.java index 71cf511ae..139b0a88d 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLActionFieldsTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLActionFieldsTest.java @@ -72,7 +72,7 @@ public class RSQLActionFieldsTest extends AbstractIntegrationTest { try { assertRSQLQuery(ActionFields.STATUS.name() + "==true", 5); - fail(); + fail("Missing expected RSQLParameterUnsupportedFieldException because status cannot be compared with 'true'"); } catch (final RSQLParameterUnsupportedFieldException e) { } } diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLUtilityTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLUtilityTest.java index 3b923d167..bcfade8d5 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLUtilityTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLUtilityTest.java @@ -63,7 +63,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterSyntaxException e) { } } @@ -75,7 +75,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing an expected RSQLParameterUnsupportedFieldException because of unknown RSQL field"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -87,7 +87,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -95,7 +95,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -103,7 +103,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, DistributionSetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -115,7 +115,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -123,7 +123,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -131,7 +131,7 @@ public class RSQLUtilityTest { try { RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - fail(); + fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } } diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/SoftwareModuleResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/SoftwareModuleResource.java index 9ce1a2975..dfbac1a6f 100644 --- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/SoftwareModuleResource.java +++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/SoftwareModuleResource.java @@ -99,52 +99,6 @@ public class SoftwareModuleResource implements SoftwareModuleRestAPI { return new ResponseEntity<>(SoftwareModuleMapper.artifactsToResponse(module.getArtifacts()), HttpStatus.OK); } - /** - * Handles the GET request for downloading an artifact. - * - * @param softwareModuleId - * of the parent SoftwareModule - * @param artifactId - * of the related LocalArtifact - * @param servletResponse - * of the servlet - * @param request - * of the client - * - * @return responseEntity with status ok if successful - */ - // @RequestMapping(method = RequestMethod.GET, value = - // RestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING - // + "/{softwareModuleId}/artifacts/{artifactId}/download") - // @ResponseBody - // public ResponseEntity downloadArtifact(@PathVariable final Long - // softwareModuleId, - // @PathVariable final Long artifactId, final HttpServletResponse - // servletResponse, - // final HttpServletRequest request) { - // final SoftwareModule module = - // findSoftwareModuleWithExceptionIfNotFound(softwareModuleId, artifactId); - // - // if (null == module || !module.getLocalArtifact(artifactId).isPresent()) { - // return new ResponseEntity<>(HttpStatus.NOT_FOUND); - // } - // - // final LocalArtifact artifact = module.getLocalArtifact(artifactId).get(); - // final DbArtifact file = - // artifactManagement.loadLocalArtifactBinary(artifact); - // - // final String ifMatch = request.getHeader("If-Match"); - // if (ifMatch != null && - // !RestResourceConversionHelper.matchesHttpHeader(ifMatch, - // artifact.getSha1Hash())) { - // return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); - // } - // - // return RestResourceConversionHelper.writeFileResponse(artifact, - // servletResponse, request, file); - // - // } - @Override public ResponseEntity getArtifact(@PathVariable final Long softwareModuleId, @PathVariable final Long artifactId) { diff --git a/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/model/ExceptionInfoTest.java b/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/model/ExceptionInfoTest.java index e9601d693..ab5012d73 100644 --- a/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/model/ExceptionInfoTest.java +++ b/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/model/ExceptionInfoTest.java @@ -32,10 +32,15 @@ public class ExceptionInfoTest { underTest.setMessage(knownMessage); underTest.setParameters(knownParameters); - assertThat(underTest.getErrorCode()).isEqualTo(knownErrorCode); - assertThat(underTest.getExceptionClass()).isEqualTo(knownExceptionClass); - assertThat(underTest.getMessage()).isEqualTo(knownMessage); - assertThat(underTest.getParameters()).isEqualTo(knownParameters); + assertThat(underTest.getErrorCode()).as("The error code should match with the known error code in the test") + .isEqualTo(knownErrorCode); + assertThat(underTest.getExceptionClass()) + .as("The exception class should match with the known error code in the test") + .isEqualTo(knownExceptionClass); + assertThat(underTest.getMessage()).as("The message should match with the known error code in the test") + .isEqualTo(knownMessage); + assertThat(underTest.getParameters()).as("The parameters should match with the known error code in the test") + .isEqualTo(knownParameters); } } diff --git a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/ExcludePathAwareShallowETagFilterTest.java b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/ExcludePathAwareShallowETagFilterTest.java index ce663fbfb..d3dc066f1 100644 --- a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/ExcludePathAwareShallowETagFilterTest.java +++ b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/ExcludePathAwareShallowETagFilterTest.java @@ -56,7 +56,8 @@ public class ExcludePathAwareShallowETagFilterTest { filterUnderTest.doFilterInternal(servletRequestMock, servletResponseMock, filterChainMock); // verify no eTag header is set and response has not been changed - assertThat(servletResponseMock.getHeader("ETag")).isNull(); + assertThat(servletResponseMock.getHeader("ETag")) + .as("ETag header should not be set during downloading, too expensive").isNull(); // the servlet response must be the same mock! verify(filterChainMock, times(1)).doFilter(servletRequestMock, servletResponseMock); } diff --git a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java index e1e809ab8..d56c59252 100644 --- a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java +++ b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java @@ -53,7 +53,8 @@ public class IpUtilTest { final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux"); // verify - assertThat(remoteAddr).isEqualTo(knownRemoteClientIP); + assertThat(remoteAddr).as("The remote address should be as the known client IP address") + .isEqualTo(knownRemoteClientIP); verify(requestMock, times(1)).getHeader("bumlux"); verify(requestMock, times(1)).getRemoteAddr(); } @@ -71,7 +72,8 @@ public class IpUtilTest { final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For"); // verify - assertThat(remoteAddr).isEqualTo(knownRemoteClientIP); + assertThat(remoteAddr).as("The remote address should be as the known client IP address") + .isEqualTo(knownRemoteClientIP); verify(requestMock, times(1)).getHeader(HttpHeaders.X_FORWARDED_FOR); verify(requestMock, times(0)).getRemoteAddr(); } @@ -94,10 +96,10 @@ public class IpUtilTest { } private void assertHttpUri(final String host, final URI httpUri) { - assertTrue(IpUtil.isHttpUri(httpUri)); - assertFalse(IpUtil.isAmqpUri(httpUri)); - assertEquals(host, httpUri.getHost()); - assertEquals("http", httpUri.getScheme()); + assertTrue("The given URI has an http scheme", IpUtil.isHttpUri(httpUri)); + assertFalse("The given URI is not an AMQP scheme", IpUtil.isAmqpUri(httpUri)); + assertEquals("The URI hosts matches the given host", host, httpUri.getHost()); + assertEquals("The given URI scheme is http", "http", httpUri.getScheme()); } @Test @@ -117,22 +119,26 @@ public class IpUtilTest { } private void assertAmqpUri(final String host, final URI httpUri) { - assertTrue(IpUtil.isAmqpUri(httpUri)); - assertFalse(IpUtil.isHttpUri(httpUri)); - assertEquals(host, httpUri.getHost()); - assertEquals("amqp", httpUri.getScheme()); + assertTrue("The given URI is an AMQP scheme", IpUtil.isAmqpUri(httpUri)); + assertFalse("The given URI is not an HTTP scheme", IpUtil.isHttpUri(httpUri)); + assertEquals("The given host matches the URI host", host, httpUri.getHost()); + assertEquals("The given URI has an AMQP scheme", "amqp", httpUri.getScheme()); } - @Test(expected = IllegalArgumentException.class) + @Test @Description("Tests create invalid uri") public void testCreateInvalidUri() { final String host = "10.99.99.1"; final URI testUri = IpUtil.createUri("test", host); - assertFalse(IpUtil.isAmqpUri(testUri)); - assertFalse(IpUtil.isHttpUri(testUri)); - assertEquals(host, testUri.getHost()); - IpUtil.createUri(":/", host); - fail(); + assertFalse("The given URI is not an AMQP address", IpUtil.isAmqpUri(testUri)); + assertFalse("The given URI is not an HTTP address", IpUtil.isHttpUri(testUri)); + assertEquals("The given host matches the URI host", host, testUri.getHost()); + try { + IpUtil.createUri(":/", host); + fail("Missing expected IllegalArgumentException due invalid URI"); + } catch (final IllegalArgumentException e) { + // expected + } } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java index 834246c63..8c1feeb33 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java @@ -108,8 +108,10 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene public OutputStream receiveUpload(final String fileName, final String mimeType) { this.fileName = fileName; this.mimeType = mimeType; + //reset has directory flag before upload + view.setHasDirectory(false); try { - if (view.validate()) { + if (view.checkIfSoftwareModuleIsSelected()) { if (view.checkForDuplicate(fileName)) { view.showDuplicateMessage(); } else { @@ -167,7 +169,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene view.updateActionCount(); // display the duplicate message after streaming all files - view.displayDuplicateMessageAfterStreamingAll(); + view.displayDuplicateValidationMessage(); } /** @@ -292,7 +294,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene if (view.enableProcessBtn()) { infoWindow.uploadSessionFinished(); } - view.displayDuplicateMessageAfterStreamingAll(); + view.displayDuplicateValidationMessage(); LOG.info("Streaming failed due to :{}", event.getException()); } @@ -316,7 +318,6 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene } view.updateActionCount(); infoWindow.uploadFailed(event.getFilename(), failureReason); - LOG.info("Upload failed for file :{}", event.getReason()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java index c12c72dd8..41304ddc9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java @@ -46,6 +46,7 @@ import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.annotation.EventBusListenerMethod; +import com.google.common.base.Strings; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptAll; @@ -116,6 +117,8 @@ public class UploadLayout extends VerticalLayout { private DragAndDropWrapper dropAreaWrapper; + private Boolean hasDirectory = Boolean.FALSE; + /** * Initialize the upload layout. */ @@ -182,27 +185,60 @@ public class UploadLayout extends VerticalLayout { @Override public void drop(final DragAndDropEvent event) { - if (validate()) { - + if (validate(event)) { final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles(); - if (files != null) { - for (final Html5File file : files) { - if (!checkForDuplicate(file.getFileName())) { - numberOfFileUploadsExpected.incrementAndGet(); - file.setStreamVariable(createStreamVariable(file)); - } - } - if (numberOfFileUploadsExpected.get() > 0) { - processBtn.setEnabled(false); - // reset before we start - uploadInfoWindow.uploadSessionStarted(); - } - // in case if all selected files are duplicate ,then display - // message - displayDuplicateMessageAfterStreamingAll(); + // reset the flag + hasDirectory = Boolean.FALSE; + for (final Html5File file : files) { + processFile(file); + } + if (numberOfFileUploadsExpected.get() > 0) { + processBtn.setEnabled(false); + // reset before we start + uploadInfoWindow.uploadSessionStarted(); + } else { + // If the upload is not started, it signifies all + // dropped files as either duplicate or directory.So + // display message accordingly + displayCompositeMessage(); } } } + + private void processFile(final Html5File file) { + if (!isDirectory(file)) { + if (!checkForDuplicate(file.getFileName())) { + numberOfFileUploadsExpected.incrementAndGet(); + file.setStreamVariable(createStreamVariable(file)); + } + } else { + hasDirectory = Boolean.TRUE; + } + } + } + + private static boolean isDirectory(final Html5File file) { + if (Strings.isNullOrEmpty(file.getType()) && file.getFileSize() % 4096 == 0) { + return true; + } + return false; + } + + private void displayCompositeMessage() { + final String duplicateMessage = getDuplicateFileValidationMessage(); + final StringBuilder compositeMessage = new StringBuilder(); + if (!Strings.isNullOrEmpty(duplicateMessage)) { + compositeMessage.append(duplicateMessage); + } + if (hasDirectory) { + if (compositeMessage.length() > 0) { + compositeMessage.append("
"); + } + compositeMessage.append(i18n.get("message.no.directory.upload")); + } + if (!compositeMessage.toString().isEmpty()) { + uiNotification.displayValidationError(compositeMessage.toString()); + } } private VerticalLayout createDropAreaLayout() { @@ -313,10 +349,33 @@ public class UploadLayout extends VerticalLayout { } } - Boolean validate() { + Boolean validate(DragAndDropEvent event) { + // check if drop is valid.If valid ,check if software module is + // selected. + if(!isFilesDropped(event)){ + uiNotification.displayValidationError(i18n.get("message.action.not.allowed")); + return false; + } + return checkIfSoftwareModuleIsSelected(); + } + + private boolean isFilesDropped(DragAndDropEvent event) { + if (event.getTransferable() instanceof WrapperTransferable) { + final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles(); + // other components can also be wrapped in WrapperTransferable , so + // additional check on files + if (files == null) { + return false; + } + return true; + } else { + return false; + } + } + + Boolean checkIfSoftwareModuleIsSelected() { if (!isSoftwareModuleSelected()) { uiNotification.displayValidationError(i18n.get("message.error.noSwModuleSelected")); - return false; } return true; @@ -381,27 +440,30 @@ public class UploadLayout extends VerticalLayout { } } - void displayDuplicateMessageAfterStreamingAll() { + void displayDuplicateValidationMessage() { // check if streaming of all dropped files are completed if (numberOfFilesActuallyUpload.intValue() == numberOfFileUploadsExpected.intValue()) { - showDuplicateMessage(); + displayCompositeMessage(); } } - /** - * Show duplicate file selected message. - */ - public void showDuplicateMessage() { + private String getDuplicateFileValidationMessage() { + StringBuilder message = new StringBuilder(); if (!duplicateFileNamesList.isEmpty()) { final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList); if (duplicateFileNamesList.size() == 1) { - uiNotification.displayValidationError(i18n.get("message.no.duplicateFile") + fileNames); + message.append(i18n.get("message.no.duplicateFile") + fileNames); } else if (duplicateFileNamesList.size() > 1) { - uiNotification.displayValidationError(i18n.get("message.no.duplicateFiles")); + message.append(i18n.get("message.no.duplicateFiles")); } duplicateFileNamesList.clear(); } + return message.toString(); + } + + public void showDuplicateMessage() { + uiNotification.displayValidationError(getDuplicateFileValidationMessage()); } void increaseNumberOfFileUploadsExpected() { @@ -593,4 +655,8 @@ public class UploadLayout extends VerticalLayout { return uiNotification; } + + public void setHasDirectory(Boolean hasDirectory) { + this.hasDirectory = hasDirectory; + } } diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 08617bd58..c63b0ba8a 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -313,7 +313,7 @@ soft.module.os =OS message.error.noFileSelected = No file selected for upload message.error.noProvidedName = Please provide custom file name message.error.noSwModuleSelected = Please select a software module -message.no.duplicateFiles = duplicate files selected +message.no.duplicateFiles = Duplicate files selected message.no.duplicateFile = Duplicate file selected : message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.duplicate.filename = Duplicate file name diff --git a/hawkbit-ui/src/main/resources/messages_de.properties b/hawkbit-ui/src/main/resources/messages_de.properties index c1d9a850f..9ff2e5e75 100644 --- a/hawkbit-ui/src/main/resources/messages_de.properties +++ b/hawkbit-ui/src/main/resources/messages_de.properties @@ -310,7 +310,7 @@ soft.module.os =OS message.error.noFileSelected = No file selected for upload message.error.noProvidedName = Please provide custom file name message.error.noSwModuleSelected = Please select a software module -message.no.duplicateFiles = duplicate files selected +message.no.duplicateFiles = Duplicate files selected message.no.duplicateFile = Duplicate file selected : message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.duplicate.filename = Duplicate file name diff --git a/hawkbit-ui/src/main/resources/messages_en.properties b/hawkbit-ui/src/main/resources/messages_en.properties index b1f95cb45..762b68c56 100644 --- a/hawkbit-ui/src/main/resources/messages_en.properties +++ b/hawkbit-ui/src/main/resources/messages_en.properties @@ -305,7 +305,7 @@ soft.module.os =OS message.error.noFileSelected = No file selected for upload message.error.noProvidedName = Please provide custom file name message.error.noSwModuleSelected = Please select a software module -message.no.duplicateFiles = duplicate files selected +message.no.duplicateFiles = Duplicate files selected message.no.duplicateFile = Duplicate file selected : message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.duplicate.filename = Duplicate file name