gt:         final byte[] source = RandomUtils.nextBytes(1024);
context: /**
   * Copyright (c) 2015 Bosch Software Innovations 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.repository.jpa;
  
  import static org.assertj.core.api.Assertions.assertThat;
  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
  
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.util.Arrays;
  import java.util.Iterator;
  import java.util.List;
  
  import org.apache.commons.lang3.RandomUtils;
  import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
  import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
  import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
  import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
  import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
  import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
  import org.eclipse.hawkbit.repository.model.Action;
  import org.eclipse.hawkbit.repository.model.Artifact;
  import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
  import org.eclipse.hawkbit.repository.model.DistributionSet;
  import org.eclipse.hawkbit.repository.model.DistributionSetType;
  import org.eclipse.hawkbit.repository.model.SoftwareModule;
  import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
  import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
  import org.eclipse.hawkbit.repository.model.Target;
  import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
  import org.eclipse.hawkbit.repository.test.matcher.Expect;
  import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
  import org.eclipse.hawkbit.repository.test.util.WithUser;
  import org.junit.Test;
  import org.springframework.data.domain.Page;
  import org.springframework.data.domain.PageRequest;
  
  import com.google.common.collect.Lists;
  import com.google.common.collect.Sets;
  
  import ru.yandex.qatools.allure.annotations.Description;
  import ru.yandex.qatools.allure.annotations.Features;
  import ru.yandex.qatools.allure.annotations.Stories;
  
  @Features("Component Tests - Repository")
  @Stories("Software Module Management")
  public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
  
      @Test
      @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
              + "of Optional not present.")
      @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
      public void nonExistingEntityAccessReturnsNotPresent() {
          final SoftwareModule module = testdataFactory.createSoftwareModuleApp();
  
          assertThat(softwareModuleManagement.get(1234L)).isNotPresent();
  
          assertThat(softwareModuleManagement.getByNameAndVersionAndType(NOT_EXIST_ID, NOT_EXIST_ID, osType.getId()))
                  .isNotPresent();
  
          assertThat(softwareModuleManagement.getMetaDataBySoftwareModuleId(module.getId(), NOT_EXIST_ID)).isNotPresent();
      }
  
      @Test
      @Description("Verifies that management queries react as specfied on calls for non existing entities "
              + " by means of throwing EntityNotFoundException.")
      @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
      public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
          final SoftwareModule module = testdataFactory.createSoftwareModuleApp();
  
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement
                          .create(Arrays.asList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))),
                  "SoftwareModuleType");
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement
                          .create(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID)),
                  "SoftwareModuleType");
  
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.createMetaData(
                          entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx")),
                  "SoftwareModule");
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.createMetaData(Arrays
                          .asList(entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))),
                  "SoftwareModule");
  
          verifyThrownExceptionBy(() -> softwareModuleManagement.delete(NOT_EXIST_IDL), "SoftwareModule");
          verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Arrays.asList(NOT_EXIST_IDL)), "SoftwareModule");
          verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"), "SoftwareModule");
          verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(module.getId(), NOT_EXIST_ID),
                  "SoftwareModuleMetadata");
  
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.updateMetaData(
                          entityFactory.softwareModuleMetadata().update(NOT_EXIST_IDL, "xxx").value("xxx")),
                  "SoftwareModule");
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.updateMetaData(
                          entityFactory.softwareModuleMetadata().update(module.getId(), NOT_EXIST_ID).value("xxx")),
                  "SoftwareModuleMetadata");
  
          verifyThrownExceptionBy(() -> softwareModuleManagement.findByAssignedTo(PAGE, NOT_EXIST_IDL),
                  "DistributionSet");
  
          verifyThrownExceptionBy(() -> softwareModuleManagement.getByNameAndVersionAndType("xxx", "xxx", NOT_EXIST_IDL),
                  "SoftwareModuleType");
  
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.getMetaDataBySoftwareModuleId(NOT_EXIST_IDL, NOT_EXIST_ID),
                  "SoftwareModule");
  
          verifyThrownExceptionBy(() -> softwareModuleManagement.findMetaDataBySoftwareModuleId(PAGE, NOT_EXIST_IDL),
                  "SoftwareModule");
          verifyThrownExceptionBy(() -> softwareModuleManagement.findMetaDataByRsql(PAGE, NOT_EXIST_IDL, "name==*"),
                  "SoftwareModule");
          verifyThrownExceptionBy(() -> softwareModuleManagement.findByType(PAGE, NOT_EXIST_IDL), "SoftwareModule");
  
          verifyThrownExceptionBy(
                  () -> softwareModuleManagement.update(entityFactory.softwareModule().update(NOT_EXIST_IDL)),
                  "SoftwareModule");
      }
  
      @Test
      @Description("Calling update without changing fields results in no recorded change in the repository including unchanged audit fields.")
      public void updateNothingResultsInUnchangedRepository() {
          final SoftwareModule ah = testdataFactory.createSoftwareModuleOs();
  
          final SoftwareModule updated = softwareModuleManagement
                  .update(entityFactory.softwareModule().update(ah.getId()));
  
          assertThat(updated.getOptLockRevision())
                  .as("Expected version number of updated entitity to be equal to created version")
                  .isEqualTo(ah.getOptLockRevision());
      }
  
      @Test
      @Description("Calling update for changed fields results in change in the repository.")
      public void updateSoftareModuleFieldsToNewValue() {
          final SoftwareModule ah = testdataFactory.createSoftwareModuleOs();
  
          final SoftwareModule updated = softwareModuleManagement
                  .update(entityFactory.softwareModule().update(ah.getId()).description("changed").vendor("changed"));
  
          assertThat(updated.getOptLockRevision()).as("Expected version number of updated entitity is")
                  .isEqualTo(ah.getOptLockRevision() + 1);
          assertThat(updated.getDescription()).as("Updated description is").isEqualTo("changed");
          assertThat(updated.getVendor()).as("Updated vendor is").isEqualTo("changed");
      }
  
      @Test
      @Description("Create Software Module call fails when called for existing entity.")
      public void createModuleCallFailsForExistingModule() {
          testdataFactory.createSoftwareModuleOs();
          try {
              testdataFactory.createSoftwareModuleOs();
              fail("Should not have worked as module already exists.");
          } catch (final EntityAlreadyExistsException e) {
  
          }
      }
  
      @Test
      @Description("searched for software modules based on the various filter options, e.g. name,desc,type, version.")
      public void findSoftwareModuleByFilters() {
          final SoftwareModule ah = softwareModuleManagement
                  .create(entityFactory.softwareModule().create().type(appType).name("agent-hub").version("1.0.1"));
          final SoftwareModule jvm = softwareModuleManagement
                  .create(entityFactory.softwareModule().create().type(runtimeType).name("oracle-jre").version("1.7.2"));
          final SoftwareModule os = softwareModuleManagement
                  .create(entityFactory.softwareModule().create().type(osType).name("poky").version("3.0.2"));
  
          final SoftwareModule ah2 = softwareModuleManagement
                  .create(entityFactory.softwareModule().create().type(appType).name("agent-hub").version("1.0.2"));
          JpaDistributionSet ds = (JpaDistributionSet) distributionSetManagement
                  .create(entityFactory.distributionSet().create().name("ds-1").version("1.0.1").type(standardDsType)
                          .modules(Arrays.asList(os.getId(), jvm.getId(), ah2.getId())));
  
          final JpaTarget target = (JpaTarget) testdataFactory.createTarget();
          ds = (JpaDistributionSet) assignSet(target, ds).getDistributionSet();
  
          // standard searches
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent()).hasSize(1);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "poky", osType.getId()).getContent().get(0))
                  .isEqualTo(os);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent())
                  .hasSize(1);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "oracle%", runtimeType.getId()).getContent().get(0))
                  .isEqualTo(jvm);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent()).hasSize(1);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0.1", appType.getId()).getContent().get(0))
                  .isEqualTo(ah);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent()).hasSize(2);
  
          // no we search with on entity marked as deleted
          softwareModuleManagement.delete(
                  softwareModuleRepository.findByAssignedToAndType(PAGE, ds, appType).getContent().get(0).getId());
  
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent()).hasSize(1);
          assertThat(softwareModuleManagement.findByTextAndType(PAGE, "1.0%", appType.getId()).getContent().get(0))
                  .isEqualTo(ah);
      }
  
      private Action assignSet(final JpaTarget target, final JpaDistributionSet ds) {
          assignDistributionSet(ds.getId(), target.getControllerId());
          assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus())
                  .isEqualTo(TargetUpdateStatus.PENDING);
          assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(ds);
          final Action action = actionRepository.findByTargetAndDistributionSet(PAGE, target, ds).getContent().get(0);
          assertThat(action).isNotNull();
          return action;
      }
  
      @Test
      @Description("Searches for software modules based on a list of IDs.")
      public void findSoftwareModulesById() {
  
          final List<Long> modules = Arrays.asList(testdataFactory.createSoftwareModuleOs().getId(),
                  testdataFactory.createSoftwareModuleApp().getId(), 624355263L);
  
          assertThat(softwareModuleManagement.get(modules)).hasSize(2);
      }
  
      @Test
      @Description("Searches for software modules by type.")
      public void findSoftwareModulesByType() {
          // found in test
          final SoftwareModule one = testdataFactory.createSoftwareModuleOs("one");
          final SoftwareModule two = testdataFactory.createSoftwareModuleOs("two");
          // ignored
          softwareModuleManagement.delete(testdataFactory.createSoftwareModuleOs("deleted").getId());
          testdataFactory.createSoftwareModuleApp();
  
          assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent())
                  .as("Expected to find the following number of modules:").hasSize(2).as("with the following elements")
                  .contains(two, one);
      }
  
      @Test
      @Description("Counts all software modules in the repsitory that are not marked as deleted.")
      public void countSoftwareModulesAll() {
          // found in test
          testdataFactory.createSoftwareModuleOs("one");
          testdataFactory.createSoftwareModuleOs("two");
          final SoftwareModule deleted = testdataFactory.createSoftwareModuleOs("deleted");
          // ignored
          softwareModuleManagement.delete(deleted.getId());
  
          assertThat(softwareModuleManagement.count()).as("Expected to find the following number of modules:")
                  .isEqualTo(2);
      }
  
      @Test
      @Description("Deletes an artifact, which is not assigned to a Distribution Set")
      public void hardDeleteOfNotAssignedArtifact() {
  
          // [STEP1]: Create SoftwareModuleX with Artifacts
          final SoftwareModule unassignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2);
          final Iterator<Artifact> artifactsIt = unassignedModule.getArtifacts().iterator();
          final Artifact artifact1 = artifactsIt.next();
          final Artifact artifact2 = artifactsIt.next();
  
          // [STEP2]: Delete unassigned SoftwareModule
          softwareModuleManagement.delete(unassignedModule.getId());
  
          // [VERIFY EXPECTED RESULT]:
          // verify: SoftwareModule is deleted
          assertThat(softwareModuleRepository.findAll()).hasSize(0);
          assertThat(softwareModuleManagement.get(unassignedModule.getId())).isNotPresent();
  
          // verify: binary data of artifact is deleted
          assertArtfiactNull(artifact1, artifact2);
  
          // verify: meta data of artifact is deleted
          assertThat(artifactRepository.findOne(artifact1.getId())).isNull();
          assertThat(artifactRepository.findOne(artifact2.getId())).isNull();
      }
  
      @Test
      @Description("Deletes an artifact, which is assigned to a DistributionSet")
      public void softDeleteOfAssignedArtifact() {
  
          // [STEP1]: Create SoftwareModuleX with ArtifactX
          SoftwareModule assignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2);
  
          // [STEP2]: Assign SoftwareModule to DistributionSet
          testdataFactory.createDistributionSet(Sets.newHashSet(assignedModule));
  
          // [STEP3]: Delete the assigned SoftwareModule
          softwareModuleManagement.delete(assignedModule.getId());
  
          // [VERIFY EXPECTED RESULT]:
          // verify: assignedModule is marked as deleted
          assignedModule = softwareModuleManagement.get(assignedModule.getId()).get();
          assertTrue("The module should be flagged as deleted", assignedModule.isDeleted());
          assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
          assertThat(softwareModuleRepository.findAll()).hasSize(1);
  
          // verify: binary data is deleted
          final Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
          final Artifact artifact1 = artifactsIt.next();
          final Artifact artifact2 = artifactsIt.next();
          assertArtfiactNull(artifact1, artifact2);
  
          // verify: artifact meta data is still available
          assertThat(artifactRepository.findOne(artifact1.getId())).isNotNull();
          assertThat(artifactRepository.findOne(artifact2.getId())).isNotNull();
      }
  
      @Test
      @Description("Delete an artifact, which has been assigned to a rolled out DistributionSet in the past")
      public void softDeleteOfHistoricalAssignedArtifact() {
  
          // Init target
          final Target target = testdataFactory.createTarget();
  
          // [STEP1]: Create SoftwareModuleX and include the new ArtifactX
          SoftwareModule assignedModule = createSoftwareModuleWithArtifacts(osType, "moduleX", "3.0.2", 2);
  
          // [STEP2]: Assign SoftwareModule to DistributionSet
          final DistributionSet disSet = testdataFactory.createDistributionSet(Sets.newHashSet(assignedModule));
  
          // [STEP3]: Assign DistributionSet to a Device
          assignDistributionSet(disSet, Arrays.asList(target));
  
          // [STEP4]: Delete the DistributionSet
          distributionSetManagement.delete(disSet.getId());
  
          // [STEP5]: Delete the assigned SoftwareModule
          softwareModuleManagement.delete(assignedModule.getId());
  
          // [VERIFY EXPECTED RESULT]:
          // verify: assignedModule is marked as deleted
          assignedModule = softwareModuleManagement.get(assignedModule.getId()).get();
          assertTrue("The found module should be flagged deleted", assignedModule.isDeleted());
          assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
          assertThat(softwareModuleRepository.findAll()).hasSize(1);
  
          // verify: binary data is deleted
          final Iterator<Artifact> artifactsIt = assignedModule.getArtifacts().iterator();
          final Artifact artifact1 = artifactsIt.next();
          final Artifact artifact2 = artifactsIt.next();
          assertArtfiactNull(artifact1, artifact2);
  
          // verify: artifact meta data is still available
          assertThat(artifactRepository.findOne(artifact1.getId())).isNotNull();
          assertThat(artifactRepository.findOne(artifact2.getId())).isNotNull();
      }
  
      @Test
      @Description("Delete an softwaremodule with an artifact, which is alsoused by another softwaremodule.")
      public void deleteSoftwareModulesWithSharedArtifact() throws IOException {
  
          // Init artifact binary data, target and DistributionSets
  