Code format hawkbit-dmf-amqp (#1936)
Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -23,6 +23,9 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrl;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystem;
|
||||
@@ -33,7 +36,6 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
|
||||
@@ -62,10 +64,6 @@ import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@ActiveProfiles({ "test" })
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("AmqpMessage Dispatcher Service Test")
|
||||
@@ -117,14 +115,10 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
private Message getCaptureAddressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
|
||||
final Target target = targetManagement
|
||||
.getByControllerID(targetAssignDistributionSetEvent.getActions().keySet().iterator().next()).get();
|
||||
return createArgumentCapture(target.getAddress());
|
||||
}
|
||||
|
||||
private Action createAction(final DistributionSet testDs) {
|
||||
return getFirstAssignedAction(assignDistributionSet(testDs, testTarget));
|
||||
protected Message createArgumentCapture(final URI uri) {
|
||||
final ArgumentCaptor<Message> argumentCaptor = ArgumentCaptor.forClass(Message.class);
|
||||
Mockito.verify(senderService).sendMessage(argumentCaptor.capture(), eq(uri));
|
||||
return argumentCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -295,6 +289,16 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
Mockito.verifyNoInteractions(senderService);
|
||||
}
|
||||
|
||||
private Message getCaptureAddressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
|
||||
final Target target = targetManagement
|
||||
.getByControllerID(targetAssignDistributionSetEvent.getActions().keySet().iterator().next()).get();
|
||||
return createArgumentCapture(target.getAddress());
|
||||
}
|
||||
|
||||
private Action createAction(final DistributionSet testDs) {
|
||||
return getFirstAssignedAction(assignDistributionSet(testDs, testTarget));
|
||||
}
|
||||
|
||||
private void assertCancelMessage(final Message sendMessage) {
|
||||
assertEventMessage(sendMessage);
|
||||
final DmfActionRequest actionId = convertMessage(sendMessage, DmfActionRequest.class);
|
||||
@@ -313,7 +317,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.containsEntry(MessageHeaderKey.TENANT, TENANT);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.containsEntry(MessageHeaderKey.TYPE,MessageType.THING_DELETED);
|
||||
.containsEntry(MessageHeaderKey.TYPE, MessageType.THING_DELETED);
|
||||
}
|
||||
|
||||
private DmfDownloadAndUpdateRequest assertDownloadAndInstallMessage(final Message sendMessage, final Long action) {
|
||||
@@ -323,7 +327,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
assertThat(downloadAndUpdateRequest.getActionId()).isEqualTo(action);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The topic of the event should contain DOWNLOAD_AND_INSTALL")
|
||||
.containsEntry(MessageHeaderKey.TOPIC,EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
.containsEntry(MessageHeaderKey.TOPIC, EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken())
|
||||
.as("Security token of target")
|
||||
.isEqualTo(TEST_TOKEN);
|
||||
@@ -346,18 +350,12 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
.containsEntry(MessageHeaderKey.THING_ID, CONTROLLER_ID);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The value of the message header TYPE should be EVENT")
|
||||
.containsEntry(MessageHeaderKey.TYPE,MessageType.EVENT);
|
||||
.containsEntry(MessageHeaderKey.TYPE, MessageType.EVENT);
|
||||
assertThat(sendMessage.getMessageProperties().getContentType())
|
||||
.as("The content type message should be " + MessageProperties.CONTENT_TYPE_JSON)
|
||||
.isEqualTo(MessageProperties.CONTENT_TYPE_JSON);
|
||||
}
|
||||
|
||||
protected Message createArgumentCapture(final URI uri) {
|
||||
final ArgumentCaptor<Message> argumentCaptor = ArgumentCaptor.forClass(Message.class);
|
||||
Mockito.verify(senderService).sendMessage(argumentCaptor.capture(), eq(uri));
|
||||
return argumentCaptor.getValue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convertMessage(final Message message, final Class<T> clazz) {
|
||||
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||
|
||||
@@ -26,6 +26,10 @@ import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
@@ -71,11 +75,6 @@ import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConversionException;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("AmqpMessage Handler Service Test")
|
||||
@@ -168,49 +167,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertReplyToCapturedField("MyTest");
|
||||
}
|
||||
|
||||
@Step
|
||||
private void processThingCreatedMessage(final String thingId, final DmfCreateThing payload) {
|
||||
final MessageProperties messageProperties = getThingCreatedMessageProperties(thingId);
|
||||
final Message message = createMessage(payload != null ? payload : new byte[0], messageProperties);
|
||||
|
||||
final Target targetMock = mock(Target.class);
|
||||
if (payload == null) {
|
||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotExist(targetIdCaptor.capture(),
|
||||
uriCaptor.capture())).thenReturn(targetMock);
|
||||
} else {
|
||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotExist(targetIdCaptor.capture(),
|
||||
uriCaptor.capture(), targetNameCaptor.capture(), targetTypeNameCaptor.capture()))
|
||||
.thenReturn(targetMock);
|
||||
if (payload.getAttributeUpdate() != null) {
|
||||
when(controllerManagementMock.updateControllerAttributes(targetIdCaptor.capture(),
|
||||
attributesCaptor.capture(), modeCaptor.capture())).thenReturn(null);
|
||||
}
|
||||
}
|
||||
when(controllerManagementMock.findActiveActionWithHighestWeight(any())).thenReturn(Optional.empty());
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, VIRTUAL_HOST);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingIdCapturedField(final String thingId) {
|
||||
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(thingId);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertReplyToCapturedField(final String replyTo) {
|
||||
assertThat(uriCaptor.getValue()).as("Uri is not right").hasToString("amqp://" + VIRTUAL_HOST + "/" + replyTo);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertInitiatorCapturedField(final String initiator) {
|
||||
assertThat(initiatorCaptor.getValue()).as("Initiator is wrong").isEqualTo(initiator);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertRemarkCapturedField(final String remark) {
|
||||
assertThat(remarkCaptor.getValue()).as("Remark is wrong").isEqualTo(remark);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the creation of a target/thing with specified name by calling the same method that incoming RabbitMQ messages would access.")
|
||||
public void createThingWithName() {
|
||||
@@ -227,11 +183,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThingNameCapturedField(knownThingName);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingNameCapturedField(final String thingName) {
|
||||
assertThat(targetNameCaptor.getValue()).as("Thing name is wrong").isEqualTo(thingName);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the creation of a target/thing with specified type name by calling the same method that incoming RabbitMQ messages would access.")
|
||||
public void createThingWithType() {
|
||||
@@ -248,11 +199,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThingTypeCapturedField(knownThingTypeName);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingTypeCapturedField(final String thingType) {
|
||||
assertThat(targetTypeNameCaptor.getValue()).as("Thing type is wrong").isEqualTo(thingType);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests not allowed body in message")
|
||||
public void createThingWithWrongBody() {
|
||||
@@ -284,11 +230,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThingAttributesCapturedField(attributeUpdate.getAttributes());
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingAttributesCapturedField(final Map<String, String> attributes) {
|
||||
assertThat(attributesCaptor.getValue()).as("Attributes is not right").isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the creation of a target/thing with specified name and attributes by calling the same method that incoming RabbitMQ messages would access.")
|
||||
public void createThingWithNameAndAttributes() {
|
||||
@@ -312,11 +253,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThingAttributesModeCapturedField(UpdateMode.REPLACE);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingAttributesModeCapturedField(final UpdateMode attributesUpdateMode) {
|
||||
assertThat(modeCaptor.getValue()).as("Attributes update mode is not right").isEqualTo(attributesUpdateMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the target attribute update by calling the same method that incoming RabbitMQ messages would access.")
|
||||
public void updateAttributes() {
|
||||
@@ -571,6 +507,35 @@ public class AmqpMessageHandlerServiceTest {
|
||||
.contains("Device reported status code: 12");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the deletion of a target/thing, requested by the target itself.")
|
||||
public void deleteThing() {
|
||||
// prepare valid message
|
||||
final String knownThingId = "1";
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_REMOVED);
|
||||
messageProperties.setHeader(MessageHeaderKey.THING_ID, knownThingId);
|
||||
final Message message = createMessage(new byte[0], messageProperties);
|
||||
|
||||
// test
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_REMOVED.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
// verify
|
||||
verify(controllerManagementMock).deleteExistingTarget(knownThingId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the deletion of a target/thing with missing thingId")
|
||||
public void deleteThingWithoutThingId() {
|
||||
// prepare invalid message
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_REMOVED);
|
||||
final Message message = createMessage(new byte[0], messageProperties);
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no thingId was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.THING_REMOVED.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests activating auto-confirmation on a target.")
|
||||
void setAutoConfirmationStateActive() {
|
||||
@@ -589,7 +554,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = createMessage(autoConfirmation, messageProperties);
|
||||
|
||||
when(controllerManagementMock.activateAutoConfirmation(targetIdCaptor.capture(), initiatorCaptor.capture(),
|
||||
remarkCaptor.capture())).thenReturn(null);
|
||||
remarkCaptor.capture())).thenReturn(null);
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
@@ -600,7 +565,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertRemarkCapturedField(remark);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Tests deactivating auto-confirmation on a target.")
|
||||
void setAutoConfirmationStateDeactivated() {
|
||||
@@ -621,6 +585,69 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThingIdCapturedField(knownThingId);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void processThingCreatedMessage(final String thingId, final DmfCreateThing payload) {
|
||||
final MessageProperties messageProperties = getThingCreatedMessageProperties(thingId);
|
||||
final Message message = createMessage(payload != null ? payload : new byte[0], messageProperties);
|
||||
|
||||
final Target targetMock = mock(Target.class);
|
||||
if (payload == null) {
|
||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotExist(targetIdCaptor.capture(),
|
||||
uriCaptor.capture())).thenReturn(targetMock);
|
||||
} else {
|
||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotExist(targetIdCaptor.capture(),
|
||||
uriCaptor.capture(), targetNameCaptor.capture(), targetTypeNameCaptor.capture()))
|
||||
.thenReturn(targetMock);
|
||||
if (payload.getAttributeUpdate() != null) {
|
||||
when(controllerManagementMock.updateControllerAttributes(targetIdCaptor.capture(),
|
||||
attributesCaptor.capture(), modeCaptor.capture())).thenReturn(null);
|
||||
}
|
||||
}
|
||||
when(controllerManagementMock.findActiveActionWithHighestWeight(any())).thenReturn(Optional.empty());
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, VIRTUAL_HOST);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingIdCapturedField(final String thingId) {
|
||||
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(thingId);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertReplyToCapturedField(final String replyTo) {
|
||||
assertThat(uriCaptor.getValue()).as("Uri is not right").hasToString("amqp://" + VIRTUAL_HOST + "/" + replyTo);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertInitiatorCapturedField(final String initiator) {
|
||||
assertThat(initiatorCaptor.getValue()).as("Initiator is wrong").isEqualTo(initiator);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertRemarkCapturedField(final String remark) {
|
||||
assertThat(remarkCaptor.getValue()).as("Remark is wrong").isEqualTo(remark);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingNameCapturedField(final String thingName) {
|
||||
assertThat(targetNameCaptor.getValue()).as("Thing name is wrong").isEqualTo(thingName);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingTypeCapturedField(final String thingType) {
|
||||
assertThat(targetTypeNameCaptor.getValue()).as("Thing type is wrong").isEqualTo(thingType);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingAttributesCapturedField(final Map<String, String> attributes) {
|
||||
assertThat(attributesCaptor.getValue()).as("Attributes is not right").isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertThingAttributesModeCapturedField(final UpdateMode attributesUpdateMode) {
|
||||
assertThat(modeCaptor.getValue()).as("Attributes update mode is not right").isEqualTo(attributesUpdateMode);
|
||||
}
|
||||
|
||||
private DmfActionUpdateStatus createActionUpdateStatus(final DmfActionStatus status) {
|
||||
return createActionUpdateStatus(status, 2L);
|
||||
}
|
||||
@@ -675,35 +702,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the deletion of a target/thing, requested by the target itself.")
|
||||
public void deleteThing() {
|
||||
// prepare valid message
|
||||
final String knownThingId = "1";
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_REMOVED);
|
||||
messageProperties.setHeader(MessageHeaderKey.THING_ID, knownThingId);
|
||||
final Message message = createMessage(new byte[0], messageProperties);
|
||||
|
||||
// test
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_REMOVED.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
// verify
|
||||
verify(controllerManagementMock).deleteExistingTarget(knownThingId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the deletion of a target/thing with missing thingId")
|
||||
public void deleteThingWithoutThingId() {
|
||||
// prepare invalid message
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_REMOVED);
|
||||
final Message message = createMessage(new byte[0], messageProperties);
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no thingId was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.THING_REMOVED.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
private MessageProperties getThingCreatedMessageProperties(final String thingId) {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
|
||||
messageProperties.setHeader(MessageHeaderKey.THING_ID, thingId);
|
||||
|
||||
@@ -13,6 +13,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
@@ -29,10 +32,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConversionException;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("Base Amqp Service Test")
|
||||
|
||||
@@ -11,35 +11,34 @@ package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Feature("Unit Tests - Delegating Conditional Error Handler")
|
||||
@Story("Delegating Conditional Error Handler")
|
||||
public class DelegatingAmqpErrorHandlerTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that with a list of conditional error handlers, the error is delegated to specific handler.")
|
||||
public void verifyDelegationHandling(){
|
||||
public void verifyDelegationHandling() {
|
||||
List<AmqpErrorHandler> handlers = new ArrayList<>();
|
||||
handlers.add(new IllegalArgumentExceptionHandler());
|
||||
handlers.add(new IndexOutOfBoundsExceptionHandler());
|
||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.as("Expected handled exception to be of type IllegalArgumentException")
|
||||
.isThrownBy(() -> new DelegatingConditionalErrorHandler(handlers, new DefaultErrorHandler())
|
||||
.handleError(new Throwable(new IllegalArgumentException())));
|
||||
.handleError(new Throwable(new IllegalArgumentException())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that default handler is used if no handlers are defined for the specific exception.")
|
||||
public void verifyDefaultDelegationHandling(){
|
||||
public void verifyDefaultDelegationHandling() {
|
||||
List<AmqpErrorHandler> handlers = new ArrayList<>();
|
||||
handlers.add(new IllegalArgumentExceptionHandler());
|
||||
handlers.add(new IndexOutOfBoundsExceptionHandler());
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.cronutils.utils.StringUtils;
|
||||
import io.qameta.allure.Step;
|
||||
import org.assertj.core.api.HamcrestCondition;
|
||||
import org.eclipse.hawkbit.amqp.DmfApiConfiguration;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||
@@ -48,9 +50,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.Mockito;
|
||||
@@ -63,12 +64,7 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.cronutils.utils.StringUtils;
|
||||
|
||||
import io.qameta.allure.Step;
|
||||
|
||||
/**
|
||||
*
|
||||
* Common class for {@link AmqpMessageHandlerServiceIntegrationTest} and
|
||||
* {@link AmqpMessageDispatcherServiceIntegrationTest}.
|
||||
*/
|
||||
@@ -131,7 +127,7 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
testdataFactory.addSoftwareModuleMetadata(distributionSet);
|
||||
|
||||
return registerTargetAndAssignDistributionSet(distributionSet.getId(), TargetUpdateStatus.REGISTERED,
|
||||
distributionSet.getModules(), controllerId);
|
||||
distributionSet.getModules(), controllerId);
|
||||
}
|
||||
|
||||
protected DistributionSetAssignmentResult prepareDistributionSetAndAssign(final String controllerId) {
|
||||
@@ -196,17 +192,6 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
|
||||
}
|
||||
|
||||
private void assertAssignmentMessage(final Set<SoftwareModule> dsModules, final String controllerId,
|
||||
final EventTopic topic) {
|
||||
final Message replyMessage = assertReplyMessageHeader(topic, controllerId);
|
||||
assertAllTargetsCount(1);
|
||||
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = (DmfDownloadAndUpdateRequest) getDmfClient()
|
||||
.getMessageConverter().fromMessage(replyMessage);
|
||||
|
||||
assertDmfDownloadAndUpdateRequest(downloadAndUpdateRequest, dsModules, controllerId);
|
||||
}
|
||||
|
||||
protected void assertDmfDownloadAndUpdateRequest(final DmfDownloadAndUpdateRequest request,
|
||||
final Set<SoftwareModule> softwareModules, final String controllerId) {
|
||||
assertSoftwareModules(softwareModules, request.getSoftwareModules());
|
||||
@@ -294,18 +279,6 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
expectedTargetStatus, createdBy, attributes, () -> targetManagement.getByControllerID(controllerId));
|
||||
}
|
||||
|
||||
private void registerAndAssertTargetWithExistingTenant(final String controllerId, final String name,
|
||||
final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus,
|
||||
final String createdBy, final Map<String, String> attributes,
|
||||
final Callable<Optional<Target>> fetchTarget) {
|
||||
createAndSendThingCreated(controllerId, name, attributes);
|
||||
final Target registeredTarget = waitUntilIsPresent(fetchTarget::call);
|
||||
assertAllTargetsCount(existingTargetsAfterCreation);
|
||||
assertThat(registeredTarget).isNotNull();
|
||||
assertTarget(registeredTarget, name != null ? name : controllerId, expectedTargetStatus, createdBy,
|
||||
attributes != null ? attributes : Collections.emptyMap());
|
||||
}
|
||||
|
||||
protected void registerSameTargetAndAssertBasedOnVersion(final String controllerId,
|
||||
final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus) {
|
||||
registerSameTargetAndAssertBasedOnVersion(controllerId, null, existingTargetsAfterCreation,
|
||||
@@ -320,27 +293,6 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
expectedTargetStatus, CREATED_BY, attributes, () -> findTargetBasedOnNewVersion(controllerId, version));
|
||||
}
|
||||
|
||||
private Optional<Target> findTargetBasedOnNewVersion(final String controllerId, final int version) {
|
||||
final Optional<Target> target2 = controllerManagement.getByControllerId(controllerId);
|
||||
if (version < target2.get().getOptLockRevision()) {
|
||||
return target2;
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private void assertTarget(final Target target, final String name, final TargetUpdateStatus updateStatus,
|
||||
final String createdBy, final Map<String, String> attributes) {
|
||||
assertThat(target.getTenant()).isEqualTo(TENANT_EXIST);
|
||||
assertThat(target.getName()).isEqualTo(name);
|
||||
assertThat(target.getDescription()).contains("Plug and Play");
|
||||
assertThat(target.getDescription()).contains(target.getControllerId());
|
||||
assertThat(target.getCreatedBy()).isEqualTo(createdBy);
|
||||
assertThat(target.getUpdateStatus()).isEqualTo(updateStatus);
|
||||
assertThat(target.getAddress())
|
||||
.isEqualTo(IpUtil.createAmqpUri(getVirtualHost(), DmfTestConfiguration.REPLY_TO_EXCHANGE));
|
||||
assertThat(targetManagement.getControllerAttributes(target.getControllerId())).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
protected Message createTargetMessage(final String controllerId, final String tenant) {
|
||||
return createTargetMessage(controllerId, null, null, tenant);
|
||||
}
|
||||
@@ -458,7 +410,7 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
}
|
||||
|
||||
protected void assertSoftwareModules(final Set<SoftwareModule> expectedSoftwareModules,
|
||||
final List<DmfSoftwareModule> softwareModules) {
|
||||
final List<DmfSoftwareModule> softwareModules) {
|
||||
assertThat(expectedSoftwareModules)
|
||||
.is(new HamcrestCondition<>(SoftwareModuleJsonMatcher.containsExactly(softwareModules)));
|
||||
softwareModules.forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
|
||||
@@ -484,4 +436,48 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
assertThat(updatedTarget.getSecurityToken()).isEqualTo(request.getTargetSecurityToken());
|
||||
}
|
||||
|
||||
private void assertAssignmentMessage(final Set<SoftwareModule> dsModules, final String controllerId,
|
||||
final EventTopic topic) {
|
||||
final Message replyMessage = assertReplyMessageHeader(topic, controllerId);
|
||||
assertAllTargetsCount(1);
|
||||
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = (DmfDownloadAndUpdateRequest) getDmfClient()
|
||||
.getMessageConverter().fromMessage(replyMessage);
|
||||
|
||||
assertDmfDownloadAndUpdateRequest(downloadAndUpdateRequest, dsModules, controllerId);
|
||||
}
|
||||
|
||||
private void registerAndAssertTargetWithExistingTenant(final String controllerId, final String name,
|
||||
final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus,
|
||||
final String createdBy, final Map<String, String> attributes,
|
||||
final Callable<Optional<Target>> fetchTarget) {
|
||||
createAndSendThingCreated(controllerId, name, attributes);
|
||||
final Target registeredTarget = waitUntilIsPresent(fetchTarget::call);
|
||||
assertAllTargetsCount(existingTargetsAfterCreation);
|
||||
assertThat(registeredTarget).isNotNull();
|
||||
assertTarget(registeredTarget, name != null ? name : controllerId, expectedTargetStatus, createdBy,
|
||||
attributes != null ? attributes : Collections.emptyMap());
|
||||
}
|
||||
|
||||
private Optional<Target> findTargetBasedOnNewVersion(final String controllerId, final int version) {
|
||||
final Optional<Target> target2 = controllerManagement.getByControllerId(controllerId);
|
||||
if (version < target2.get().getOptLockRevision()) {
|
||||
return target2;
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private void assertTarget(final Target target, final String name, final TargetUpdateStatus updateStatus,
|
||||
final String createdBy, final Map<String, String> attributes) {
|
||||
assertThat(target.getTenant()).isEqualTo(TENANT_EXIST);
|
||||
assertThat(target.getName()).isEqualTo(name);
|
||||
assertThat(target.getDescription()).contains("Plug and Play");
|
||||
assertThat(target.getDescription()).contains(target.getControllerId());
|
||||
assertThat(target.getCreatedBy()).isEqualTo(createdBy);
|
||||
assertThat(target.getUpdateStatus()).isEqualTo(updateStatus);
|
||||
assertThat(target.getAddress())
|
||||
.isEqualTo(IpUtil.createAmqpUri(getVirtualHost(), DmfTestConfiguration.REPLY_TO_EXCHANGE));
|
||||
assertThat(targetManagement.getControllerAttributes(target.getControllerId())).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionRequest;
|
||||
@@ -80,13 +83,10 @@ import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.amqp.core.Message;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("Amqp Message Dispatcher Service")
|
||||
public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpServiceIntegrationTest {
|
||||
|
||||
private static final String TARGET_PREFIX = "Dmf_disp_";
|
||||
|
||||
@Test
|
||||
@@ -140,7 +140,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void sendDownloadAndInstallStatusMessageDuringMaintenanceWindow() {
|
||||
public void sendDownloadAndInstallStatusMessageDuringMaintenanceWindow() {
|
||||
final String controllerId = TARGET_PREFIX + "sendDAndIStatusMessageDuringWindow";
|
||||
|
||||
registerAndAssertTargetWithExistingTenant(controllerId);
|
||||
@@ -242,7 +242,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
.setActionType(ActionType.DOWNLOAD_ONLY).setWeight(weight1).build()).getAssignedEntity().get(0).getId();
|
||||
final Long cancelActionId = makeAssignment(
|
||||
DeploymentManagement.deploymentRequest(controllerId, ds.getId()).setWeight(DEFAULT_TEST_WEIGHT).build())
|
||||
.getAssignedEntity().get(0).getId();
|
||||
.getAssignedEntity().get(0).getId();
|
||||
// make sure the latest message in the queue is the one triggered by the
|
||||
// cancellation
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.DOWNLOAD_AND_INSTALL, EventTopic.MULTI_ACTION,
|
||||
@@ -274,14 +274,6 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
controllerId);
|
||||
}
|
||||
|
||||
private List<DmfMultiActionElement> getLatestMultiActionMessages(final String expectedControllerId) {
|
||||
final Message multiactionMessage = replyToListener.getLatestEventMessage(EventTopic.MULTI_ACTION);
|
||||
assertThat(multiactionMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID))
|
||||
.isEqualTo(expectedControllerId);
|
||||
return ((DmfMultiActionRequest) getDmfClient().getMessageConverter().fromMessage(multiactionMessage))
|
||||
.getElements();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Handle cancelation process of an action in multi assignment mode.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@@ -376,24 +368,6 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
assertLatestMultiActionMessage(controllerId, Arrays.asList(action1Install, action2Install));
|
||||
}
|
||||
|
||||
private void updateActionViaDmfClient(final String controllerId, final long actionId,
|
||||
final DmfActionStatus status) {
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, status);
|
||||
}
|
||||
|
||||
private Long assignNewDsToTarget(final String controllerId) {
|
||||
return assignNewDsToTarget(controllerId, null);
|
||||
}
|
||||
|
||||
private Long assignNewDsToTarget(final String controllerId, final Integer weight) {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds.getId(), Collections.singletonList(controllerId), ActionType.FORCED,
|
||||
RepositoryModelConstants.NO_FORCE_TIME, weight));
|
||||
waitUntilTargetHasStatus(controllerId, TargetUpdateStatus.PENDING);
|
||||
return actionId;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("If multi assignment is enabled multiple rollouts with the same DS lead to multiple actions.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@@ -474,18 +448,6 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
assertLatestMultiActionMessageContainsInstallMessages(controllerId, Collections.singletonList(smIds1));
|
||||
}
|
||||
|
||||
private Set<Long> getSoftwareModuleIds(final DistributionSet ds) {
|
||||
return ds.getModules().stream().map(SoftwareModule::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Rollout createAndStartRollout(final DistributionSet ds, final String filterQuery, final Integer weight) {
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(UUID.randomUUID().toString(), "", 1,
|
||||
filterQuery, ds, "50", "5", ActionType.FORCED, weight, false);
|
||||
rolloutManagement.start(rollout.getId());
|
||||
rolloutHandler.handleAll();
|
||||
return rollout;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a cancel assignment send a cancel message.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@@ -577,6 +539,169 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
assertThat(assignedDistributionSet.getId()).isEqualTo(distributionSet.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignment download and install message.")
|
||||
public void assertBatchAssignmentsDownloadAndInstall() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignments download only message.")
|
||||
public void assertBatchAssignmentsDownloadOnly() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD);
|
||||
}
|
||||
|
||||
protected void assertDmfBatchDownloadAndUpdateRequest(final DmfBatchDownloadAndUpdateRequest request,
|
||||
final Set<SoftwareModule> softwareModules,
|
||||
final List<String> controllerIds) {
|
||||
assertSoftwareModules(softwareModules, request.getSoftwareModules());
|
||||
|
||||
final List<Object> tokens = controllerIds.stream().map(controllerId -> {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
assertThat(target).isPresent();
|
||||
return target.get().getSecurityToken();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
final List<DmfTarget> requestTargets = request.getTargets();
|
||||
|
||||
assertThat(requestTargets).hasSameSizeAs(controllerIds);
|
||||
requestTargets.forEach(requestTarget -> {
|
||||
assertThat(requestTarget).isNotNull();
|
||||
assertThat(tokens.contains(requestTarget.getTargetSecurityToken()));
|
||||
});
|
||||
}
|
||||
|
||||
protected void assertEventMessageNotPresent(final EventTopic eventTopic) {
|
||||
assertThat(replyToListener.getLatestEventMessage(eventTopic)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that batch and multi-assignments can't be activated at the same time.")
|
||||
void assertBatchAndMultiAssignmentsNotCompatible() {
|
||||
enableBatchAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableMultiAssignments());
|
||||
disableBatchAssignments();
|
||||
|
||||
enableMultiAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableBatchAssignments());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(names = { "BATCH_DOWNLOAD_AND_INSTALL", "BATCH_DOWNLOAD" })
|
||||
@Description("Verify payload of batch assignments.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 3), @Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = TargetPollEvent.class, count = 3),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void assertBatchAssignmentsMessagePayload(final EventTopic topic) {
|
||||
enableBatchAssignments();
|
||||
|
||||
final List<String> targets = Arrays.asList("batchCtrlID1", "batchCtrlID2", "batchCtrlID3");
|
||||
for (int i = 0; i < targets.size(); i++) {
|
||||
registerAndAssertTargetWithExistingTenant(targets.get(i), i + 1);
|
||||
}
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
testdataFactory.addSoftwareModuleMetadata(ds);
|
||||
|
||||
assignDistributionSet(ds.getId(), targets, topic == BATCH_DOWNLOAD ? DOWNLOAD_ONLY : FORCED);
|
||||
|
||||
waitUntilEventMessagesAreDispatchedToTarget(topic);
|
||||
|
||||
final Message message = replyToListener.getLatestEventMessage(topic);
|
||||
final Map<String, Object> headers = message.getMessageProperties().getHeaders();
|
||||
assertThat(headers).containsEntry("type", EVENT.toString());
|
||||
assertThat(headers).containsEntry("topic", topic.toString());
|
||||
|
||||
final DmfBatchDownloadAndUpdateRequest batchRequest = (DmfBatchDownloadAndUpdateRequest) getDmfClient()
|
||||
.getMessageConverter().fromMessage(message);
|
||||
|
||||
assertThat(batchRequest).isExactlyInstanceOf(DmfBatchDownloadAndUpdateRequest.class);
|
||||
assertDmfBatchDownloadAndUpdateRequest(batchRequest, ds.getModules(), targets);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a distribution assignment send a confirm message.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void sendConfirmStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "sendConfirmStatus";
|
||||
enableConfirmationFlow();
|
||||
registerTargetAndAssignDistributionSet(controllerId);
|
||||
|
||||
waitUntilTargetHasStatus(controllerId, TargetUpdateStatus.PENDING);
|
||||
assertConfirmMessage(getDistributionSet().getModules(), controllerId);
|
||||
assertEventMessageNotPresent(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
private static Set<Long> getSmIds(final DmfDownloadAndUpdateRequest request) {
|
||||
return request.getSoftwareModules().stream().map(DmfSoftwareModule::getModuleId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private static List<DmfDownloadAndUpdateRequest> getDownloadAndUpdateRequests(final DmfMultiActionRequest request) {
|
||||
return request.getElements().stream()
|
||||
.filter(AmqpMessageDispatcherServiceIntegrationTest::isDownloadAndUpdateRequest)
|
||||
.map(multiAction -> (DmfDownloadAndUpdateRequest) multiAction.getAction()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static boolean isDownloadAndUpdateRequest(final DmfMultiActionElement multiActionElement) {
|
||||
return multiActionElement.getTopic().equals(EventTopic.DOWNLOAD)
|
||||
|| multiActionElement.getTopic().equals(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
private List<DmfMultiActionElement> getLatestMultiActionMessages(final String expectedControllerId) {
|
||||
final Message multiactionMessage = replyToListener.getLatestEventMessage(EventTopic.MULTI_ACTION);
|
||||
assertThat(multiactionMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID))
|
||||
.isEqualTo(expectedControllerId);
|
||||
return ((DmfMultiActionRequest) getDmfClient().getMessageConverter().fromMessage(multiactionMessage))
|
||||
.getElements();
|
||||
}
|
||||
|
||||
private void updateActionViaDmfClient(final String controllerId, final long actionId,
|
||||
final DmfActionStatus status) {
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, status);
|
||||
}
|
||||
|
||||
private Long assignNewDsToTarget(final String controllerId) {
|
||||
return assignNewDsToTarget(controllerId, null);
|
||||
}
|
||||
|
||||
private Long assignNewDsToTarget(final String controllerId, final Integer weight) {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds.getId(), Collections.singletonList(controllerId), ActionType.FORCED,
|
||||
RepositoryModelConstants.NO_FORCE_TIME, weight));
|
||||
waitUntilTargetHasStatus(controllerId, TargetUpdateStatus.PENDING);
|
||||
return actionId;
|
||||
}
|
||||
|
||||
private Set<Long> getSoftwareModuleIds(final DistributionSet ds) {
|
||||
return ds.getModules().stream().map(SoftwareModule::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Rollout createAndStartRollout(final DistributionSet ds, final String filterQuery, final Integer weight) {
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(UUID.randomUUID().toString(), "", 1,
|
||||
filterQuery, ds, "50", "5", ActionType.FORCED, weight, false);
|
||||
rolloutManagement.start(rollout.getId());
|
||||
rolloutHandler.handleAll();
|
||||
return rollout;
|
||||
}
|
||||
|
||||
private void waitUntilTargetHasStatus(final String controllerId, final TargetUpdateStatus status) {
|
||||
waitUntil(() -> {
|
||||
final Optional<Target> findTargetByControllerID = targetManagement.getByControllerID(controllerId);
|
||||
@@ -614,129 +739,4 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
.map(request -> new SimpleEntry<>(request.getAction().getActionId(), request.getTopic()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Set<Long> getSmIds(final DmfDownloadAndUpdateRequest request) {
|
||||
return request.getSoftwareModules().stream().map(DmfSoftwareModule::getModuleId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private static List<DmfDownloadAndUpdateRequest> getDownloadAndUpdateRequests(final DmfMultiActionRequest request) {
|
||||
return request.getElements().stream()
|
||||
.filter(AmqpMessageDispatcherServiceIntegrationTest::isDownloadAndUpdateRequest)
|
||||
.map(multiAction -> (DmfDownloadAndUpdateRequest) multiAction.getAction()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static boolean isDownloadAndUpdateRequest(final DmfMultiActionElement multiActionElement) {
|
||||
return multiActionElement.getTopic().equals(EventTopic.DOWNLOAD)
|
||||
|| multiActionElement.getTopic().equals(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignment download and install message.")
|
||||
public void assertBatchAssignmentsDownloadAndInstall() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignments download only message.")
|
||||
public void assertBatchAssignmentsDownloadOnly() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that batch and multi-assignments can't be activated at the same time.")
|
||||
void assertBatchAndMultiAssignmentsNotCompatible() {
|
||||
enableBatchAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableMultiAssignments());
|
||||
disableBatchAssignments();
|
||||
|
||||
enableMultiAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableBatchAssignments());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(names = { "BATCH_DOWNLOAD_AND_INSTALL", "BATCH_DOWNLOAD" })
|
||||
@Description("Verify payload of batch assignments.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 3), @Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = TargetPollEvent.class, count = 3),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void assertBatchAssignmentsMessagePayload(final EventTopic topic) {
|
||||
enableBatchAssignments();
|
||||
|
||||
final List<String> targets = Arrays.asList("batchCtrlID1", "batchCtrlID2", "batchCtrlID3");
|
||||
for (int i = 0; i < targets.size(); i++) {
|
||||
registerAndAssertTargetWithExistingTenant(targets.get(i), i+1);
|
||||
}
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
testdataFactory.addSoftwareModuleMetadata(ds);
|
||||
|
||||
assignDistributionSet(ds.getId(), targets, topic == BATCH_DOWNLOAD?DOWNLOAD_ONLY:FORCED);
|
||||
|
||||
waitUntilEventMessagesAreDispatchedToTarget(topic);
|
||||
|
||||
final Message message = replyToListener.getLatestEventMessage(topic);
|
||||
final Map<String, Object> headers = message.getMessageProperties().getHeaders();
|
||||
assertThat(headers).containsEntry("type", EVENT.toString());
|
||||
assertThat(headers).containsEntry("topic",topic.toString());
|
||||
|
||||
final DmfBatchDownloadAndUpdateRequest batchRequest = (DmfBatchDownloadAndUpdateRequest) getDmfClient()
|
||||
.getMessageConverter().fromMessage(message);
|
||||
|
||||
assertThat(batchRequest).isExactlyInstanceOf(DmfBatchDownloadAndUpdateRequest.class);
|
||||
assertDmfBatchDownloadAndUpdateRequest(batchRequest, ds.getModules(), targets);
|
||||
}
|
||||
|
||||
protected void assertDmfBatchDownloadAndUpdateRequest(final DmfBatchDownloadAndUpdateRequest request,
|
||||
final Set<SoftwareModule> softwareModules,
|
||||
final List<String> controllerIds) {
|
||||
assertSoftwareModules(softwareModules, request.getSoftwareModules());
|
||||
|
||||
final List<Object> tokens = controllerIds.stream().map(controllerId -> {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
assertThat(target).isPresent();
|
||||
return target.get().getSecurityToken();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
final List<DmfTarget> requestTargets = request.getTargets();
|
||||
|
||||
assertThat(requestTargets).hasSameSizeAs(controllerIds);
|
||||
requestTargets.forEach(requestTarget -> {
|
||||
assertThat(requestTarget).isNotNull();
|
||||
assertThat(tokens.contains(requestTarget.getTargetSecurityToken()));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a distribution assignment send a confirm message.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void sendConfirmStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "sendConfirmStatus";
|
||||
enableConfirmationFlow();
|
||||
registerTargetAndAssignDistributionSet(controllerId);
|
||||
|
||||
waitUntilTargetHasStatus(controllerId, TargetUpdateStatus.PENDING);
|
||||
assertConfirmMessage(getDistributionSet().getModules(), controllerId);
|
||||
assertEventMessageNotPresent(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
protected void assertEventMessageNotPresent(final EventTopic eventTopic) {
|
||||
assertThat(replyToListener.getLatestEventMessage(eventTopic)).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,12 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.amqp.AmqpMessageHandlerService;
|
||||
import org.eclipse.hawkbit.amqp.AmqpProperties;
|
||||
@@ -37,12 +43,12 @@ import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
@@ -63,8 +69,8 @@ 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.TargetTestData;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
import org.eclipse.hawkbit.repository.test.util.TargetTestData;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
@@ -74,22 +80,14 @@ import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("Amqp Message Handler Service")
|
||||
class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegrationTest {
|
||||
private static final String TARGET_PREFIX = "Dmf_hand_";
|
||||
|
||||
public static final String DMF_REGISTER_TEST_CONTROLLER_ID = "Dmf_hand_registerTargets_1";
|
||||
public static final String DMF_ATTR_TEST_CONTROLLER_ID = "Dmf_hand_updateAttributes";
|
||||
public static final String UPDATE_ATTR_TEST_CONTROLLER_ID = "ControllerAttributeTestTarget";
|
||||
|
||||
private static final String TARGET_PREFIX = "Dmf_hand_";
|
||||
@Autowired
|
||||
private AmqpProperties amqpProperties;
|
||||
|
||||
@@ -179,7 +177,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"", "Invalid Invalid"})
|
||||
@ValueSource(strings = { "", "Invalid Invalid" })
|
||||
@NullSource
|
||||
@Description("Tests register invalid target with empty controller id.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
@@ -309,7 +307,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"", "NotExist"})
|
||||
@ValueSource(strings = { "", "NotExist" })
|
||||
@NullSource
|
||||
@Description("Tests null type message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
@@ -323,7 +321,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"", "NotExist"})
|
||||
@ValueSource(strings = { "", "NotExist" })
|
||||
@NullSource
|
||||
@Description("Tests null topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
@@ -347,7 +345,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "", "Invalid Content"})
|
||||
@ValueSource(strings = { "", "Invalid Content" })
|
||||
@NullSource
|
||||
@Description("Tests invalid null message content. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
@@ -688,84 +686,6 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeRemove() {
|
||||
|
||||
// assemble the expected attributes
|
||||
final Map<String, String> expectedAttributes = targetManagement
|
||||
.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID);
|
||||
expectedAttributes.remove("k1");
|
||||
expectedAttributes.remove("k3");
|
||||
|
||||
// send an update message with update mode
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
|
||||
final DmfAttributeUpdate remove = new DmfAttributeUpdate();
|
||||
remove.setMode(DmfUpdateMode.REMOVE);
|
||||
remove.getAttributes().putAll(removeAttributes);
|
||||
sendUpdateAttributeMessage(remove);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeMerge() {
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID));
|
||||
|
||||
// send an update message with update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
|
||||
final DmfAttributeUpdate merge = new DmfAttributeUpdate();
|
||||
merge.setMode(DmfUpdateMode.MERGE);
|
||||
merge.getAttributes().putAll(mergeAttributes);
|
||||
sendUpdateAttributeMessage(merge);
|
||||
|
||||
// validate
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.putAll(attributes);
|
||||
expectedAttributes.putAll(mergeAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeReplace() {
|
||||
// send an update message with update mode REPLACE
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k1", "v1_modified");
|
||||
expectedAttributes.put("k2", "v2");
|
||||
expectedAttributes.put("k3", "v3");
|
||||
|
||||
final DmfAttributeUpdate replace = new DmfAttributeUpdate();
|
||||
replace.setMode(DmfUpdateMode.REPLACE);
|
||||
replace.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(replace);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithoutUpdateMode() {
|
||||
// send an update message which does not specify an update mode
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k0", "v0");
|
||||
expectedAttributes.put("k1", "v1");
|
||||
|
||||
final DmfAttributeUpdate defaultUpdate = new DmfAttributeUpdate();
|
||||
defaultUpdate.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(defaultUpdate);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that sending an update controller attribute message with no thingid header to an existing target does not work.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@@ -917,6 +837,234 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Register a target and send a update action status (confirmed). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void confirmedActionStatus() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.CONFIRMED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION, Status.RUNNING);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.CONFIRM, EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF confirmed feedback can be provided if confirmation flow is disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationUpdatedEvent.class, count = 1) })
|
||||
void verifyActionCanBeConfirmedOnDisabledConfirmationFlow() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
disableConfirmationFlow();
|
||||
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.CONFIRMED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION, Status.RUNNING);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.CONFIRM, EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF confirmed feedback can be provided if confirmation flow is disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationUpdatedEvent.class, count = 1) })
|
||||
void verifyActionCanBeDeniedOnDisabledConfirmationFlow() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
disableConfirmationFlow();
|
||||
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DENIED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF download and install message is send directly if auto-confirmation is active")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void verifyDownloadAndInstallDirectlySendOnAutoConfirmationEnabled() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
registerAndAssertTargetWithExistingTenant(controllerId);
|
||||
|
||||
confirmationManagement.activateAutoConfirmation(controllerId, null, null);
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = prepareDistributionSetAndAssign(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Register a target and send a update action status (denied). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void deniedActionStatus() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "deniedActionStatus";
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DENIED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION);
|
||||
}
|
||||
|
||||
private static String getActionIdFromBody(final byte[] body) throws IOException {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
final ObjectNode node = objectMapper.readValue(new String(body, Charset.defaultCharset()), ObjectNode.class);
|
||||
assertThat(node.has("actionId")).isTrue();
|
||||
return node.get("actionId").asText();
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeRemove() {
|
||||
|
||||
// assemble the expected attributes
|
||||
final Map<String, String> expectedAttributes = targetManagement
|
||||
.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID);
|
||||
expectedAttributes.remove("k1");
|
||||
expectedAttributes.remove("k3");
|
||||
|
||||
// send an update message with update mode
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
|
||||
final DmfAttributeUpdate remove = new DmfAttributeUpdate();
|
||||
remove.setMode(DmfUpdateMode.REMOVE);
|
||||
remove.getAttributes().putAll(removeAttributes);
|
||||
sendUpdateAttributeMessage(remove);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeMerge() {
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID));
|
||||
|
||||
// send an update message with update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
|
||||
final DmfAttributeUpdate merge = new DmfAttributeUpdate();
|
||||
merge.setMode(DmfUpdateMode.MERGE);
|
||||
merge.getAttributes().putAll(mergeAttributes);
|
||||
sendUpdateAttributeMessage(merge);
|
||||
|
||||
// validate
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.putAll(attributes);
|
||||
expectedAttributes.putAll(mergeAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeReplace() {
|
||||
// send an update message with update mode REPLACE
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k1", "v1_modified");
|
||||
expectedAttributes.put("k2", "v2");
|
||||
expectedAttributes.put("k3", "v3");
|
||||
|
||||
final DmfAttributeUpdate replace = new DmfAttributeUpdate();
|
||||
replace.setMode(DmfUpdateMode.REPLACE);
|
||||
replace.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(replace);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithoutUpdateMode() {
|
||||
// send an update message which does not specify an update mode
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k0", "v0");
|
||||
expectedAttributes.put("k1", "v1");
|
||||
|
||||
final DmfAttributeUpdate defaultUpdate = new DmfAttributeUpdate();
|
||||
defaultUpdate.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(defaultUpdate);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void verifyAssignedDsAndInstalledDs(final Long assignedDsId, final Long installedDsId) {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(DMF_REGISTER_TEST_CONTROLLER_ID);
|
||||
@@ -1014,6 +1162,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int getAuthenticationMessageCount() {
|
||||
return Integer
|
||||
.parseInt(Objects.requireNonNull(getRabbitAdmin().getQueueProperties(amqpProperties.getReceiverQueue()))
|
||||
@@ -1034,155 +1183,4 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
|
||||
.verify(getDeadletterListener(), Mockito.times(numberOfInvocations)).handleMessage(Mockito.any()));
|
||||
Mockito.reset(getDeadletterListener());
|
||||
}
|
||||
|
||||
private static String getActionIdFromBody(final byte[] body) throws IOException {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
final ObjectNode node = objectMapper.readValue(new String(body, Charset.defaultCharset()), ObjectNode.class);
|
||||
assertThat(node.has("actionId")).isTrue();
|
||||
return node.get("actionId").asText();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Register a target and send a update action status (confirmed). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void confirmedActionStatus() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.CONFIRMED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION, Status.RUNNING);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.CONFIRM, EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF confirmed feedback can be provided if confirmation flow is disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationUpdatedEvent.class, count = 1) })
|
||||
void verifyActionCanBeConfirmedOnDisabledConfirmationFlow() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
disableConfirmationFlow();
|
||||
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.CONFIRMED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION, Status.RUNNING);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.CONFIRM, EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF confirmed feedback can be provided if confirmation flow is disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationUpdatedEvent.class, count = 1)})
|
||||
void verifyActionCanBeDeniedOnDisabledConfirmationFlow() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
disableConfirmationFlow();
|
||||
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DENIED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the DMF download and install message is send directly if auto-confirmation is active")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void verifyDownloadAndInstallDirectlySendOnAutoConfirmationEnabled() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "confirmedActionStatus";
|
||||
|
||||
registerAndAssertTargetWithExistingTenant(controllerId);
|
||||
|
||||
confirmationManagement.activateAutoConfirmation(controllerId, null, null);
|
||||
|
||||
final DistributionSetAssignmentResult assignmentResult = prepareDistributionSetAndAssign(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
// verify action status is in WAIT_FOR_CONFIRMATION
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
|
||||
// assert download and install message
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(assignmentResult.getDistributionSet().getModules(), controllerId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Register a target and send a update action status (denied). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 9), // implicit lock
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void deniedActionStatus() {
|
||||
enableConfirmationFlow();
|
||||
final String controllerId = TARGET_PREFIX + "deniedActionStatus";
|
||||
final DistributionSetAssignmentResult assignmentResult = registerTargetAndAssignDistributionSet(controllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
assertActionStatusList(actionId, 1, Status.WAIT_FOR_CONFIRMATION);
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DENIED);
|
||||
assertActionStatusList(actionId, 2, Status.WAIT_FOR_CONFIRMATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,16 +33,15 @@ public final class SoftwareModuleJsonMatcher {
|
||||
* <code>null</code>
|
||||
* <p>
|
||||
* For example:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* List<SoftwareModule> modules;
|
||||
* List<org.eclipse.hawkbit.dmf.json.model.SoftwareModule> expectedModules;
|
||||
*
|
||||
*
|
||||
* assertThat(modules, containsExactly(expectedModules));
|
||||
* </pre>
|
||||
*
|
||||
* @param expectedModules
|
||||
* the json sofware modules.
|
||||
*
|
||||
* @param expectedModules the json sofware modules.
|
||||
*/
|
||||
public static SoftwareModulesMatcher containsExactly(final List<DmfSoftwareModule> expectedModules) {
|
||||
return new SoftwareModulesMatcher(expectedModules);
|
||||
@@ -56,13 +55,22 @@ public final class SoftwareModuleJsonMatcher {
|
||||
this.expectedModules = expectedModules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final Object actualValue) {
|
||||
return containsExactly(actualValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(final Description description) {
|
||||
description.appendValue(expectedModules);
|
||||
}
|
||||
|
||||
boolean containsExactly(final Object actual) {
|
||||
if (actual == null) {
|
||||
return expectedModules == null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Collection<SoftwareModule> modules = (Collection<SoftwareModule>) actual;
|
||||
@SuppressWarnings("unchecked") final Collection<SoftwareModule> modules = (Collection<SoftwareModule>) actual;
|
||||
|
||||
return expectedModules.stream().allMatch(e -> existsIn(e, modules));
|
||||
}
|
||||
@@ -73,16 +81,6 @@ public final class SoftwareModuleJsonMatcher {
|
||||
&& module.getModuleVersion().equals(e.getVersion())
|
||||
&& module.getArtifacts().size() == e.getArtifacts().size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final Object actualValue) {
|
||||
return containsExactly(actualValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(final Description description) {
|
||||
description.appendValue(expectedModules);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user