Introduce new DMF message THING_REMOVED (#891)
* Introduce new DMF message THING_REMOVED Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch-si.com> * rename test to its original name Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch-si.com> * API documentation adapted; constant defined for duplicated string Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch-si.com> * Resolve review comments; Replace try/catch blocks in exceptions testing Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch-si.com> * Re-add finally block in test cases Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch-si.com>
This commit is contained in:
committed by
Dominic Schabel
parent
8687510131
commit
193603282a
@@ -58,6 +58,28 @@ Header
|
||||
----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------
|
||||
type=THING\_CREATED <br /> tenant=tenant123 <br /> thingId=abc <br /> sender=Lwm2m | content\_type=application/json <br /> reply_to (optional) =sp.connector.replyTo
|
||||
|
||||
|
||||
### THING_REMOVED
|
||||
|
||||
Message to request the deletion of a provisioning target.
|
||||
|
||||
Header | Description | Type | Mandatory
|
||||
-------------- | ------------------------------------------------ | ---------------------------- | -------------------------------------------------------------
|
||||
type | Type of the message | Fixed string "THING_REMOVED" | true
|
||||
thingId | The ID of the registered provisioning target | String | true
|
||||
tenant | The tenant this provisioning target belongs to | String | false
|
||||
|
||||
Message Properties | Description | Type | Mandatory
|
||||
------------------ | ---------------------------------------------------------------------------------------------------- | ------ | -------------------------------------------------------------
|
||||
content_type | The content type of the payload | String | true
|
||||
|
||||
Example headers
|
||||
|
||||
Header | MessageProperties
|
||||
----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------
|
||||
type=THING\_REMOVED <br /> tenant=tenant123 <br /> thingId=abc | content\_type=application/json
|
||||
|
||||
|
||||
### UPDATE_ATTRIBUTES
|
||||
|
||||
Message to update target attributes. This message can be send in response to a _REQUEST_ATTRIBUTES_UPDATE_ event, sent by hawkBit.
|
||||
|
||||
@@ -82,6 +82,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
|
||||
private static final String THING_ID_NULL = "ThingId is null";
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -156,6 +158,10 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
setTenantSecurityContext(tenant);
|
||||
registerTarget(message, virtualHost);
|
||||
break;
|
||||
case THING_REMOVED:
|
||||
setTenantSecurityContext(tenant);
|
||||
deleteTarget(message);
|
||||
break;
|
||||
case EVENT:
|
||||
checkContentTypeJson(message);
|
||||
setTenantSecurityContext(tenant);
|
||||
@@ -200,7 +206,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
* the ip of the target/thing
|
||||
*/
|
||||
private void registerTarget(final Message message, final String virtualHost) {
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, "ThingId is null");
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, THING_ID_NULL);
|
||||
final String replyTo = message.getMessageProperties().getReplyTo();
|
||||
|
||||
if (StringUtils.isEmpty(replyTo)) {
|
||||
@@ -274,8 +280,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
*
|
||||
* @param message
|
||||
* the incoming event message.
|
||||
* @param topic
|
||||
* the topic of the event.
|
||||
*/
|
||||
private void handleIncomingEvent(final Message message) {
|
||||
switch (EventTopic.valueOf(getStringHeaderKey(message, MessageHeaderKey.TOPIC, "EventTopic is null"))) {
|
||||
@@ -292,9 +296,14 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
|
||||
}
|
||||
|
||||
private void deleteTarget(final Message message) {
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, THING_ID_NULL);
|
||||
controllerManagement.deleteExistingTarget(thingId);
|
||||
}
|
||||
|
||||
private void updateAttributes(final Message message) {
|
||||
final DmfAttributeUpdate attributeUpdate = convertMessage(message, DmfAttributeUpdate.class);
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, "ThingId is null");
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, THING_ID_NULL);
|
||||
|
||||
controllerManagement.updateControllerAttributes(thingId, attributeUpdate.getAttributes(),
|
||||
getUpdateMode(attributeUpdate));
|
||||
@@ -303,7 +312,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
/**
|
||||
* Method to update the action status of an action through the event.
|
||||
*
|
||||
* @param actionUpdateStatus
|
||||
* @param message
|
||||
* the object form the ampq message
|
||||
*/
|
||||
private void updateActionStatus(final Message message) {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -82,10 +82,14 @@ import io.qameta.allure.Story;
|
||||
@Story("AmqpMessage Handler Service Test")
|
||||
public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
private static final String FAIL_MESSAGE_AMQP_REJECT_REASON = AmqpRejectAndDontRequeueException.class.getSimpleName()
|
||||
+ " was expected, ";
|
||||
|
||||
private static final String SHA1 = "12345";
|
||||
private static final String VIRTUAL_HOST = "vHost";
|
||||
private static final String TENANT = "DEFAULT";
|
||||
private static final Long TENANT_ID = 123L;
|
||||
private static final String CONTROLLLER_ID = "123";
|
||||
private static final String CONTROLLER_ID = "123";
|
||||
private static final Long TARGET_ID = 123L;
|
||||
|
||||
private AmqpMessageHandlerService amqpMessageHandlerService;
|
||||
@@ -162,11 +166,10 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setContentType("xml");
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to worng content type");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "due to wrong content type")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -185,12 +188,11 @@ public class AmqpMessageHandlerServiceTest {
|
||||
uriCaptor.capture())).thenReturn(targetMock);
|
||||
when(controllerManagementMock.findOldestActiveActionByTarget(any())).thenReturn(Optional.empty());
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
// verify
|
||||
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(knownThingId);
|
||||
assertThat(uriCaptor.getValue().toString()).as("Uri is not right").isEqualTo("amqp://vHost/MyTest");
|
||||
|
||||
assertThat(uriCaptor.getValue().toString()).as("Uri is not right").isEqualTo("amqp://"+VIRTUAL_HOST+"/MyTest");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -210,13 +212,12 @@ public class AmqpMessageHandlerServiceTest {
|
||||
when(controllerManagementMock.updateControllerAttributes(targetIdCaptor.capture(), attributesCaptor.capture(),
|
||||
modeCaptor.capture())).thenReturn(null);
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
// verify
|
||||
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(knownThingId);
|
||||
assertThat(attributesCaptor.getValue()).as("Attributes is not right")
|
||||
.isEqualTo(attributeUpdate.getAttributes());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -235,7 +236,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
// send a message which does not specify a update mode
|
||||
Message message = amqpMessageHandlerService.getMessageConverter().toMessage(attributeUpdate, messageProperties);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
// verify that NO fallback is made on the way to the controller
|
||||
// management layer
|
||||
assertThat(modeCaptor.getValue()).isNull();
|
||||
@@ -243,40 +244,36 @@ public class AmqpMessageHandlerServiceTest {
|
||||
// send a message which specifies update mode MERGE
|
||||
attributeUpdate.setMode(DmfUpdateMode.MERGE);
|
||||
message = amqpMessageHandlerService.getMessageConverter().toMessage(attributeUpdate, messageProperties);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
// verify that the update mode is converted and forwarded as expected
|
||||
assertThat(modeCaptor.getValue()).isEqualTo(UpdateMode.MERGE);
|
||||
|
||||
// send a message which specifies update mode REPLACE
|
||||
attributeUpdate.setMode(DmfUpdateMode.REPLACE);
|
||||
message = amqpMessageHandlerService.getMessageConverter().toMessage(attributeUpdate, messageProperties);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
// verify that the update mode is converted and forwarded as expected
|
||||
assertThat(modeCaptor.getValue()).isEqualTo(UpdateMode.REPLACE);
|
||||
|
||||
// send a message which specifies update mode REMOVE
|
||||
attributeUpdate.setMode(DmfUpdateMode.REMOVE);
|
||||
message = amqpMessageHandlerService.getMessageConverter().toMessage(attributeUpdate, messageProperties);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
// verify that the update mode is converted and forwarded as expected
|
||||
assertThat(modeCaptor.getValue()).isEqualTo(UpdateMode.REMOVE);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the creation of a thing without a 'reply to' header in message.")
|
||||
public void createThingWitoutReplyTo() {
|
||||
public void createThingWithoutReplyTo() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED, null);
|
||||
messageProperties.setHeader(MessageHeaderKey.THING_ID, "1");
|
||||
final Message message = messageConverter.toMessage("", messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no replyTo header was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no replyTo header was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -284,12 +281,11 @@ public class AmqpMessageHandlerServiceTest {
|
||||
public void createThingWithoutID() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
|
||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no thingID was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no thingId was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -300,12 +296,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
messageProperties.setHeader(MessageHeaderKey.THING_ID, "");
|
||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "due to unknown message type")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, type, TENANT, VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -313,27 +306,23 @@ public class AmqpMessageHandlerServiceTest {
|
||||
public void invalidEventTopic() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, "unknownMessageType", TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown topic");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "due to unknown message type")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, "unknownMessageType", TENANT,
|
||||
VIRTUAL_HOST));
|
||||
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "due to unknown topic")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted because there was no event topic");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "because there was no event topic")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -346,12 +335,10 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(actionUpdateStatus,
|
||||
messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no action id was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -365,20 +352,17 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(actionUpdateStatus,
|
||||
messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
assertThatExceptionOfType(AmqpRejectAndDontRequeueException.class)
|
||||
.as(FAIL_MESSAGE_AMQP_REJECT_REASON + "since no action id was set")
|
||||
.isThrownBy(() -> amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT,
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an download request is denied for an artifact which does not exists")
|
||||
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLLER_ID,
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
@@ -397,7 +381,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
||||
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLLER_ID,
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
@@ -419,7 +403,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
||||
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLLER_ID,
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
@@ -473,7 +457,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, VIRTUAL_HOST);
|
||||
|
||||
final ArgumentCaptor<ActionProperties> actionPropertiesCaptor = ArgumentCaptor.forClass(ActionProperties.class);
|
||||
final ArgumentCaptor<Target> targetCaptor = ArgumentCaptor.forClass(Target.class);
|
||||
@@ -485,7 +469,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThat(actionProperties.getTenant()).as("event has tenant").isEqualTo("DEFAULT");
|
||||
assertThat(targetCaptor.getValue().getControllerId()).as("event has wrong controller id").isEqualTo("target1");
|
||||
assertThat(actionProperties.getId()).as("event has wrong action id").isEqualTo(22L);
|
||||
|
||||
}
|
||||
|
||||
private DmfActionUpdateStatus createActionUpdateStatus(final DmfActionStatus status) {
|
||||
@@ -515,7 +498,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
private Action createActionWithTarget(final Long targetId, final Status status) throws IllegalAccessException {
|
||||
// is needed for the creation of targets
|
||||
initalizeSecurityTokenGenerator();
|
||||
initializeSecurityTokenGenerator();
|
||||
|
||||
// Mock
|
||||
final Action actionMock = mock(Action.class);
|
||||
@@ -531,7 +514,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
return actionMock;
|
||||
}
|
||||
|
||||
private void initalizeSecurityTokenGenerator() throws IllegalAccessException {
|
||||
private void initializeSecurityTokenGenerator() throws IllegalAccessException {
|
||||
final SecurityTokenGeneratorHolder instance = SecurityTokenGeneratorHolder.getInstance();
|
||||
final Field[] fields = instance.getClass().getDeclaredFields();
|
||||
for (final Field field : fields) {
|
||||
@@ -541,4 +524,34 @@ 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 = messageConverter.toMessage(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 = messageConverter.toMessage(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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,13 +29,18 @@ public enum MessageType {
|
||||
*/
|
||||
THING_DELETED,
|
||||
|
||||
/**
|
||||
* The request to delete a target.
|
||||
*/
|
||||
THING_REMOVED,
|
||||
|
||||
/**
|
||||
* DMF receiver health check type.
|
||||
*/
|
||||
PING,
|
||||
|
||||
/**
|
||||
* DMF receiver health check reponse type.
|
||||
* DMF receiver health check response type.
|
||||
*/
|
||||
PING_RESPONSE
|
||||
|
||||
|
||||
@@ -48,14 +48,14 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Adds an {@link ActionStatus} for a cancel {@link Action} including
|
||||
* potential state changes for the target and the {@link Action} itself.
|
||||
*
|
||||
*
|
||||
* @param create
|
||||
* to be added
|
||||
* @return the updated {@link Action}
|
||||
*
|
||||
*
|
||||
* @throws EntityAlreadyExistsException
|
||||
* if a given entity already exists
|
||||
*
|
||||
*
|
||||
* @throws QuotaExceededException
|
||||
* if more than the allowed number of status entries or messages
|
||||
* per entry are inserted
|
||||
@@ -64,14 +64,14 @@ public interface ControllerManagement {
|
||||
* @throws ConstraintViolationException
|
||||
* if fields are not filled as specified. Check
|
||||
* {@link ActionStatusCreate} for field constraints.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
Action addCancelActionStatus(@NotNull @Valid ActionStatusCreate create);
|
||||
|
||||
/**
|
||||
* Retrieves assigned {@link SoftwareModule} of a target.
|
||||
*
|
||||
*
|
||||
* @param moduleId
|
||||
* of the {@link SoftwareModule}
|
||||
* @return {@link SoftwareModule} identified by ID
|
||||
@@ -82,7 +82,7 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Retrieves {@link SoftwareModuleMetadata} where
|
||||
* {@link SoftwareModuleMetadata#isTargetVisible()}.
|
||||
*
|
||||
*
|
||||
* @param moduleId
|
||||
* of the {@link SoftwareModule}
|
||||
* @return list of {@link SoftwareModuleMetadata} with maximum size of
|
||||
@@ -95,12 +95,12 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Simple addition of a new {@link ActionStatus} entry to the {@link Action}
|
||||
* . No state changes.
|
||||
*
|
||||
*
|
||||
* @param create
|
||||
* to add to the action
|
||||
*
|
||||
*
|
||||
* @return created {@link ActionStatus} entity
|
||||
*
|
||||
*
|
||||
* @throws QuotaExceededException
|
||||
* if more than the allowed number of status entries or messages
|
||||
* per entry are inserted
|
||||
@@ -138,15 +138,15 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Retrieves oldest {@link Action} that is active and assigned to a
|
||||
* {@link Target}.
|
||||
*
|
||||
*
|
||||
* For performance reasons this method does not throw
|
||||
* {@link EntityNotFoundException} in case target with given controlelrId
|
||||
* {@link EntityNotFoundException} in case target with given controllerId
|
||||
* does not exist but will return an {@link Optional#empty()} instead.
|
||||
*
|
||||
* @param controllerId
|
||||
* identifies the target to retrieve the actions from
|
||||
* @return a list of actions assigned to given target which are active
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
Optional<Action> findOldestActiveActionByTarget(@NotEmpty String controllerId);
|
||||
@@ -154,7 +154,7 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Retrieves all active actions which are assigned to the target with the
|
||||
* given controller ID.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* pagination parameter
|
||||
* @param controllerId
|
||||
@@ -184,7 +184,7 @@ public interface ControllerManagement {
|
||||
* @param actionId
|
||||
* to be filtered on
|
||||
* @return the corresponding {@link Page} of {@link ActionStatus}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -217,7 +217,7 @@ public interface ControllerManagement {
|
||||
* of the the {@link SoftwareModule} that should be assigned to
|
||||
* the target
|
||||
* @return last {@link Action} for given combination
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*
|
||||
@@ -244,7 +244,7 @@ public interface ControllerManagement {
|
||||
|
||||
/**
|
||||
* Returns the count to be used for reducing polling interval while calling
|
||||
* {@link ControllerManagement#getPollingTimeForAction()}.
|
||||
* {@link ControllerManagement#getPollingTimeForAction(long)}.
|
||||
*
|
||||
* @return configured value of
|
||||
* {@link TenantConfigurationKey#MAINTENANCE_WINDOW_POLL_COUNT}.
|
||||
@@ -277,7 +277,7 @@ public interface ControllerManagement {
|
||||
* a target is allowed to download a given artifact because it has currently
|
||||
* assigned or had ever been assigned to the target and so it's visible to a
|
||||
* specific target e.g. for downloading.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* the ID of the target to check
|
||||
* @param sha1Hash
|
||||
@@ -286,7 +286,7 @@ public interface ControllerManagement {
|
||||
* @return {@code true} if the given target has currently or had ever a
|
||||
* relation to the given artifact through the action history,
|
||||
* otherwise {@code false}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -299,7 +299,7 @@ public interface ControllerManagement {
|
||||
* a target is allowed to download a given artifact because it has currently
|
||||
* assigned or had ever been assigned to the target and so it's visible to a
|
||||
* specific target e.g. for downloading.
|
||||
*
|
||||
*
|
||||
* @param targetId
|
||||
* the ID of the target to check
|
||||
* @param sha1Hash
|
||||
@@ -308,7 +308,7 @@ public interface ControllerManagement {
|
||||
* @return {@code true} if the given target has currently or had ever a
|
||||
* relation to the given artifact through the action history,
|
||||
* otherwise {@code false}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -325,7 +325,7 @@ public interface ControllerManagement {
|
||||
* for the status
|
||||
* @return the update action in case the status has been changed to
|
||||
* {@link Status#RETRIEVED}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -432,7 +432,7 @@ public interface ControllerManagement {
|
||||
|
||||
/**
|
||||
* Updates given {@link Action} with its external id.
|
||||
*
|
||||
*
|
||||
* @param actionId
|
||||
* to be updated
|
||||
* @param externalRef
|
||||
@@ -451,4 +451,13 @@ public interface ControllerManagement {
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
List<Action> getActiveActionsByExternalRef(@NotNull List<String> externalRefs);
|
||||
|
||||
/**
|
||||
* Delete a single target.
|
||||
*
|
||||
* @param controllerId
|
||||
* of the target to delete
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
void deleteExistingTarget(@NotEmpty String controllerId);
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
|
||||
/**
|
||||
* Returns the count to be used for reducing polling interval while calling
|
||||
* {@link ControllerManagement#getPollingTimeForAction()}.
|
||||
* {@link ControllerManagement#getPollingTimeForAction(long)}.
|
||||
*
|
||||
* @return configured value of
|
||||
* {@link TenantConfigurationKey#MAINTENANCE_WINDOW_POLL_COUNT}.
|
||||
@@ -243,7 +243,7 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
* @param minimumEventInterval
|
||||
* for loading {@link DistributionSet#getModules()}. This
|
||||
* puts a lower bound to the timer value
|
||||
* @param timerUnit
|
||||
* @param timeUnit
|
||||
* representing the unit of time to be used for timer.
|
||||
*/
|
||||
EventTimer(final String defaultEventInterval, final String minimumEventInterval, final TemporalUnit timeUnit) {
|
||||
@@ -375,6 +375,13 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
return actionRepository.findByExternalRefInAndActive(externalRefs, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExistingTarget(@NotEmpty String controllerId) {
|
||||
final Target target = targetRepository.findByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
targetRepository.deleteById(target.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
@Retryable(include = ConcurrencyFailureException.class, exclude = EntityAlreadyExistsException.class, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
@@ -997,8 +1004,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
* Cancels given {@link Action} for this {@link Target}. The method will
|
||||
* immediately add a {@link Status#CANCELED} status to the action. However,
|
||||
* it might be possible that the controller will continue to work on the
|
||||
* cancelation. The controller needs to acknowledge or reject the
|
||||
* cancelation using {@link DdiRootController#postCancelActionFeedback}.
|
||||
* cancellation. The controller needs to acknowledge or reject the
|
||||
* cancellation using {@link DdiRootController#postCancelActionFeedback}.
|
||||
*
|
||||
* @param actionId
|
||||
* to be canceled
|
||||
|
||||
@@ -14,7 +14,6 @@ import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpre
|
||||
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TestdataFactory.DEFAULT_CONTROLLER_ID;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -40,6 +39,7 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.UpdateMode;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
||||
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;
|
||||
@@ -51,6 +51,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
@@ -89,7 +90,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
private RepositoryProperties repositoryProperties;
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access react as specfied on calls for non existing entities by means "
|
||||
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1)})
|
||||
@@ -110,7 +111,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management queries react as specfied on calls for non existing entities "
|
||||
@Description("Verifies that management queries react as specified on calls for non existing entities "
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1)})
|
||||
@@ -147,7 +148,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller confirms successfull update with FINISHED status.")
|
||||
@Description("Controller confirms successful update with FINISHED status.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@@ -170,7 +171,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller confirmation failes with invalid messages.")
|
||||
@Description("Controller confirmation fails with invalid messages.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@@ -182,23 +183,23 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
simulateIntermediateStatusOnUpdate(actionId);
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set invalid description text should not be created")
|
||||
.isThrownBy(() -> controllerManagement.addUpdateActionStatus(entityFactory.actionStatus()
|
||||
.create(actionId).status(Action.Status.FINISHED).message(INVALID_TEXT_HTML)))
|
||||
.as("set invalid description text should not be created");
|
||||
.create(actionId).status(Action.Status.FINISHED).message(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set invalid description text should not be created")
|
||||
.isThrownBy(() -> controllerManagement.addUpdateActionStatus(
|
||||
entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED)
|
||||
.messages(Arrays.asList("this is valid.", INVALID_TEXT_HTML))))
|
||||
.as("set invalid description text should not be created");
|
||||
.messages(Arrays.asList("this is valid.", INVALID_TEXT_HTML))));
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(6);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller confirms successfull update with FINISHED status on a action that is on canceling. "
|
||||
+ "Reason: The decission to ignore the cancellation is in fact up to the controller.")
|
||||
@Description("Controller confirms successful update with FINISHED status on a action that is on canceling. "
|
||||
+ "Reason: The decision to ignore the cancellation is in fact up to the controller.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@@ -207,7 +208,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void controllerConfirmsUpdateWithFinishedAndIgnorsCancellationWithThat() {
|
||||
public void controllerConfirmsUpdateWithFinishedAndIgnoresCancellationWithThat() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
|
||||
@@ -221,7 +222,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Update server rejects cancelation feedback if action is not in CANCELING state.")
|
||||
@Description("Update server rejects cancellation feedback if action is not in CANCELING state.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@@ -230,24 +231,20 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
public void cancellationFeedbackRejectedIfActionIsNotInCanceling() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
try {
|
||||
controllerManagement.addCancelActionStatus(
|
||||
entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
fail("Expected " + CancelActionNotAllowedException.class.getName());
|
||||
} catch (final CancelActionNotAllowedException e) {
|
||||
// expected
|
||||
}
|
||||
assertThatExceptionOfType(CancelActionNotAllowedException.class)
|
||||
.as("Expected " + CancelActionNotAllowedException.class.getName())
|
||||
.isThrownBy(() -> controllerManagement.addCancelActionStatus(
|
||||
entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED)));
|
||||
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING,
|
||||
Action.Status.RUNNING, true);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(1);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller confirms action cancelation with FINISHED status.")
|
||||
@Description("Controller confirms action cancellation with FINISHED status.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@@ -255,7 +252,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void controllerConfirmsActionCancelationWithFinished() {
|
||||
public void controllerConfirmsActionCancellationWithFinished() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -274,7 +271,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller confirms action cancelation with FINISHED status.")
|
||||
@Description("Controller confirms action cancellation with FINISHED status.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@@ -282,7 +279,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void controllerConfirmsActionCancelationWithCanceled() {
|
||||
public void controllerConfirmsActionCancellationWithCanceled() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -301,7 +298,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller rejects action cancelation with CANCEL_REJECTED status. Action goes back to RUNNING status as it expects "
|
||||
@Description("Controller rejects action cancellation with CANCEL_REJECTED status. Action goes back to RUNNING status as it expects "
|
||||
+ "that the controller will continue the original update.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@@ -310,7 +307,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void controllerRejectsActionCancelationWithReject() {
|
||||
public void controllerRejectsActionCancellationWithReject() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -329,7 +326,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller rejects action cancelation with ERROR status. Action goes back to RUNNING status as it expects "
|
||||
@Description("Controller rejects action cancellation with ERROR status. Action goes back to RUNNING status as it expects "
|
||||
+ "that the controller will continue the original update.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@@ -338,7 +335,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void controllerRejectsActionCancelationWithError() {
|
||||
public void controllerRejectsActionCancellationWithError() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -466,7 +463,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that assignement verification works based on SHA1 hash. By design it is not important which artifact "
|
||||
@Description("Verifies that assignment verification works based on SHA1 hash. By design it is not important which artifact "
|
||||
+ "is actually used for the check as long as they have an identical binary, i.e. same SHA1 hash. ")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||
@@ -511,28 +508,28 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
final Target sameTarget = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target.getId()).as("Target should be the equals").isEqualTo(sameTarget.getId());
|
||||
assertThat(targetRepository.count()).as("Only 1 target should be registred").isEqualTo(1L);
|
||||
assertThat(targetRepository.count()).as("Only 1 target should be registered").isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tries to register a target with an invalid controller id")
|
||||
public void findOrRegisterTargetIfItDoesNotExistThrowsExceptionForInvalidControllerIdParam() {
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(null, LOCALHOST))
|
||||
.as("register target with null as controllerId should fail");
|
||||
.as("register target with null as controllerId should fail")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(null, LOCALHOST));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist("", LOCALHOST))
|
||||
.as("register target with empty controllerId should fail");
|
||||
.as("register target with empty controllerId should fail")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist("", LOCALHOST));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(" ", LOCALHOST))
|
||||
.as("register target with empty controllerId should fail");
|
||||
.as("register target with empty controllerId should fail")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(" ", LOCALHOST));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("register target with too long controllerId should fail")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(
|
||||
RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1), LOCALHOST))
|
||||
.as("register target with too long controllerId should fail");
|
||||
RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1), LOCALHOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -544,11 +541,13 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(mockTargetRepository);
|
||||
|
||||
try {
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
fail("Expected an ConcurrencyFailureException to be thrown!");
|
||||
} catch (final ConcurrencyFailureException e) {
|
||||
assertThatExceptionOfType(ConcurrencyFailureException.class)
|
||||
.as("Expected an ConcurrencyFailureException to be thrown!")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST));
|
||||
|
||||
verify(mockTargetRepository, times(TX_RT_MAX)).findOne(any());
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
// revert
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(targetRepository);
|
||||
}
|
||||
@@ -593,12 +592,13 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
when(mockTargetRepository.save(any())).thenThrow(EntityAlreadyExistsException.class);
|
||||
|
||||
try {
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("1234", LOCALHOST);
|
||||
fail("Expected an EntityAlreadyExistsException to be thrown!");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
assertThatExceptionOfType(EntityAlreadyExistsException.class)
|
||||
.as("Expected an EntityAlreadyExistsException to be thrown!")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist("1234", LOCALHOST));
|
||||
verify(mockTargetRepository, times(1)).findOne(any());
|
||||
verify(mockTargetRepository, times(1)).save(any());
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
// revert
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(targetRepository);
|
||||
}
|
||||
@@ -615,11 +615,13 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
when(mockTargetRepository.findOne(any())).thenThrow(RuntimeException.class);
|
||||
|
||||
try {
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("aControllerId", LOCALHOST);
|
||||
fail("Expected a RuntimeException to be thrown!");
|
||||
} catch (final RuntimeException e) {
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.as("Expected a RuntimeException to be thrown!")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist("aControllerId",
|
||||
LOCALHOST));
|
||||
verify(mockTargetRepository, times(1)).findOne(any());
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
// revert
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(targetRepository);
|
||||
}
|
||||
@@ -639,7 +641,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
set.getModules().stream().map(SoftwareModule::getId).collect(Collectors.toList()));
|
||||
|
||||
assertThat(result).hasSize(3);
|
||||
result.entrySet().forEach(entry -> assertThat(entry.getValue()).hasSize(1));
|
||||
result.forEach((key, value) -> assertThat(value).hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -684,7 +686,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
Action.Status.ERROR, false);
|
||||
|
||||
// try with enabled late feedback - should not make a difference as it
|
||||
// only allows intermediate feedbacks and not multiple close
|
||||
// only allows intermediate feedback and not multiple close
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(false);
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
@@ -699,7 +701,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to finish an update process after it has been finished by an FINISHED action status.")
|
||||
@Description("Controller tries to finish an update process after it has been finished by an FINISHED action status.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@@ -720,7 +722,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
Action.Status.FINISHED, false);
|
||||
|
||||
// try with enabled late feedback - should not make a difference as it
|
||||
// only allows intermediate feedbacks and not multiple close
|
||||
// only allows intermediate feedback and not multiple close
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(false);
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
@@ -735,7 +737,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to send an update feedback after it has been finished which is reject as the repository is "
|
||||
@Description("Controller tries to send an update feedback after it has been finished which is reject as the repository is "
|
||||
+ "configured to reject that.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@@ -744,7 +746,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void sendUpdatesForFinishUpdateProcessDropedIfDisabled() {
|
||||
public void sendUpdatesForFinishUpdateProcessDroppedIfDisabled() {
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(true);
|
||||
|
||||
final Action action = prepareFinishedUpdate();
|
||||
@@ -762,7 +764,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to send an update feedback after it has been finished which is accepted as the repository is "
|
||||
@Description("Controller tries to send an update feedback after it has been finished which is accepted as the repository is "
|
||||
+ "configured to accept them.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@@ -1001,24 +1003,24 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
testdataFactory.createTarget(controllerId);
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyTooLong, valueValid), null))
|
||||
.as("Attribute with key too long should not be created");
|
||||
Collections.singletonMap(keyTooLong, valueValid), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key too long and value too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyTooLong, valueTooLong), null))
|
||||
.as("Attribute with key too long and value too long should not be created");
|
||||
Collections.singletonMap(keyTooLong, valueTooLong), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with value too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyValid, valueTooLong), null))
|
||||
.as("Attribute with value too long should not be created");
|
||||
Collections.singletonMap(keyValid, valueTooLong), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key NULL should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyNull, valueValid), null))
|
||||
.as("Attribute with key NULL should not be created");
|
||||
Collections.singletonMap(keyNull, valueValid), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1253,32 +1255,26 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void quotaEceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForDownloadOnlyAction() {
|
||||
public void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForDownloadOnlyAction() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
fail("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates")
|
||||
.isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED))));
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)));
|
||||
fail("No QuotaExceededException thrown for too many ERROR updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many ERROR updateActionStatus updates")
|
||||
.isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR))));
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)));
|
||||
fail("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates")
|
||||
.isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1288,35 +1284,29 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void quotaEceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForForced() {
|
||||
public void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForForced() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
assertThat(actionId).isNotNull();
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
fail("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates")
|
||||
.isThrownBy( ()-> IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED))));
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)));
|
||||
fail("No QuotaExceededException thrown for too many ERROR updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many ERROR updateActionStatus updates")
|
||||
.isThrownBy(()->IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR))));
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)));
|
||||
fail("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates");
|
||||
} catch (final QuotaExceededException e) {
|
||||
}
|
||||
assertThatExceptionOfType(QuotaExceededException.class)
|
||||
.as("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates")
|
||||
.isThrownBy(()->IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the attaching externalRef to an action is propery stored")
|
||||
@Description("Verify that the attaching externalRef to an action is properly stored")
|
||||
public void updatedExternalRefOnActionIsReallyUpdated() {
|
||||
final List<String> allExternalRef = new ArrayList<>();
|
||||
final List<Long> allActionId = new ArrayList<>();
|
||||
@@ -1324,15 +1314,15 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet knownDistributionSet = testdataFactory.createDistributionSet();
|
||||
for (int i = 0; i < numberOfActions; i++) {
|
||||
final String knownControllerId = "controllerId" + i;
|
||||
final String knownExternalref = "externalRefId" + i;
|
||||
final String knownExternalRef = "externalRefId" + i;
|
||||
|
||||
testdataFactory.createTarget(knownControllerId);
|
||||
final DistributionSetAssignmentResult assignmentResult = assignDistributionSet(knownDistributionSet.getId(),
|
||||
knownControllerId);
|
||||
final Long actionId = getFirstAssignedActionId(assignmentResult);
|
||||
controllerManagement.updateActionExternalRef(actionId, knownExternalref);
|
||||
controllerManagement.updateActionExternalRef(actionId, knownExternalRef);
|
||||
|
||||
allExternalRef.add(knownExternalref);
|
||||
allExternalRef.add(knownExternalRef);
|
||||
allActionId.add(actionId);
|
||||
}
|
||||
|
||||
@@ -1346,11 +1336,9 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verify that a null externalRef cannot be assigned to an action")
|
||||
public void externalRefCannotBeNull() {
|
||||
try {
|
||||
controllerManagement.updateActionExternalRef(1L, null);
|
||||
fail("No ConstraintViolationException thrown when a null externalRef was set on an action");
|
||||
} catch (final ConstraintViolationException e) {
|
||||
}
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("No ConstraintViolationException thrown when a null externalRef was set on an action")
|
||||
.isThrownBy(() -> controllerManagement.updateActionExternalRef(1L, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1470,4 +1458,47 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(controllerId)).isEqualTo(false);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Delete a target on requested target deletion from client side")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TargetDeletedEvent.class, count = 1)})
|
||||
public void deleteTargetWithValidThingId() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target).as("target should not be null").isNotNull();
|
||||
assertThat(targetRepository.count()).as("target exists and is ready for deletion").isEqualTo(1L);
|
||||
|
||||
controllerManagement.deleteExistingTarget(target.getControllerId());
|
||||
|
||||
assertThat(targetRepository.count()).as("target should not exist anymore").isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Delete a target with a non existing thingId")
|
||||
@ExpectEvents({@Expect(type = TargetDeletedEvent.class, count = 0)})
|
||||
public void deleteTargetWithInvalidThingId() {
|
||||
assertThatExceptionOfType(EntityNotFoundException.class)
|
||||
.as("No EntityNotFoundException thrown when deleting a non-existing target")
|
||||
.isThrownBy(() -> controllerManagement.deleteExistingTarget("BB"));
|
||||
assertThat(targetRepository.count()).as("target should not exist").isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Delete a target after it has been deleted already")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TargetDeletedEvent.class, count = 1)})
|
||||
public void deleteTargetAfterItWasDeleted() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target).as("target should not be null").isNotNull();
|
||||
assertThat(targetRepository.count()).as("target exists and is ready for deletion").isEqualTo(1L);
|
||||
|
||||
controllerManagement.deleteExistingTarget(target.getControllerId());
|
||||
assertThat(targetRepository.count()).as("target should not exist anymore").isEqualTo(0L);
|
||||
|
||||
assertThatExceptionOfType(EntityNotFoundException.class)
|
||||
.as("No EntityNotFoundException thrown when deleting a non-existing target")
|
||||
.isThrownBy(() -> controllerManagement.deleteExistingTarget(target.getControllerId()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user