/*
* Copyright (C) 2015 Orange
*
* This software is distributed under the terms and conditions of the 'GNU GENERAL PUBLIC LICENSE
* Version 2' license which can be found in the file 'LICENSE.txt' in this package distribution or
* at 'http://www.gnu.org/licenses/gpl-2.0-standalone.html'.
*/
package com.orange.cepheus.broker.controller;
import com.orange.cepheus.broker.Application;
import com.orange.cepheus.broker.Configuration;
import com.orange.cepheus.broker.LocalRegistrations;
import com.orange.cepheus.broker.Subscriptions;
import com.orange.cepheus.broker.exception.RegistrationException;
import com.orange.cepheus.broker.exception.RegistrationPersistenceException;
import com.orange.cepheus.broker.exception.SubscriptionException;
import com.orange.cepheus.broker.exception.SubscriptionPersistenceException;
import com.orange.cepheus.broker.model.Subscription;
import com.orange.ngsi.client.NgsiClient;
import com.orange.ngsi.model.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.context.WebApplicationContext;
import java.net.URI;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import static com.orange.cepheus.broker.Util.*;
import static com.orange.cepheus.broker.Util.createSubscribeContextTemperature;
import static com.orange.cepheus.broker.Util.createUpdateContextResponseTempSensorAndPressure;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.atLeastOnce;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
/**
* Tests for the NGSI controller
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class NgsiControllerTest {
private MockMvc mockMvc;
@Mock
LocalRegistrations localRegistrations;
@Mock
Subscriptions subscriptions;
@Mock
NgsiClient ngsiClient;
@Mock
Configuration configuration;
@Mock
Iterator<URI> providingApplication;
@Mock
Iterator<Subscription> matchedSubscriptions;
@Mock
ListenableFuture<UpdateContextResponse> updateContextResponseListenableFuture;
@Mock
ListenableFuture<QueryContextResponse> queryContextResponseListenableFuture;
@Mock
ListenableFuture<NotifyContextResponse> notifyContextResponseListenableFuture;
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private MappingJackson2HttpMessageConverter mapper;
@Captor
private ArgumentCaptor<Set<String>> attributeArgumentCaptor;
@Captor
private ArgumentCaptor<EntityId> entityIdArgumentCaptor;
@InjectMocks
@Autowired
private NgsiController ngsiController;
private HttpHeaders httpHeaders = new HttpHeaders();
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockMvc = webAppContextSetup(webApplicationContext).build();
when(configuration.getLocalUrl()).thenReturn("http://localhost:8081");
when(configuration.getRemoteUrl()).thenReturn("http://orionhost:9999");
when(configuration.getRemoteServiceName()).thenReturn(null);
when(configuration.getRemoteServicePath()).thenReturn(null);
when(configuration.getRemoteAuthToken()).thenReturn(null);
when(configuration.isRemoteForwardUpdateContext()).thenReturn(true);
when(updateContextResponseListenableFuture.get()).thenReturn(createUpdateContextResponseTempSensorAndPressure());
doNothing().when(updateContextResponseListenableFuture).addCallback(any(), any());
when(queryContextResponseListenableFuture.get()).thenReturn(createQueryContextResponseTemperature());
doNothing().when(notifyContextResponseListenableFuture).addCallback(any(), any());
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
when(ngsiClient.getRequestHeaders(any())).thenReturn(httpHeaders);
}
@After
public void resetMocks() {
reset(localRegistrations);
reset(subscriptions);
reset(ngsiClient);
reset(configuration);
reset(providingApplication);
reset(matchedSubscriptions);
reset(updateContextResponseListenableFuture);
reset(notifyContextResponseListenableFuture);
}
@Test
public void postRegisterContextWithEmptyContextRegistrations() throws Exception {
mockMvc.perform(post("/v1/registerContext")
.content(json(mapper, new RegisterContext()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value(CodeEnum.CODE_471.getLabel()))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value(CodeEnum.CODE_471.getShortPhrase()))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details")
.value("The parameter contextRegistrations of type List<ContextRegistration> is missing in the request"));
}
@Test
public void postRegisterContextWithBadContextRegistrations() throws Exception {
// RegisterContext with a bad pattern
RegisterContext registerContext = createRegistrationContext();
registerContext.getContextRegistrationList().get(0).getEntityIdList().get(0).setId("]|,\\((");
registerContext.getContextRegistrationList().get(0).getEntityIdList().get(0).setIsPattern(true);
when(localRegistrations.updateRegistrationContext(any())).thenThrow(new RegistrationException("bad pattern", new RuntimeException()));
mockMvc.perform(post("/v1/registerContext").content(json(mapper, registerContext)).contentType(MediaType.APPLICATION_JSON))
.andDo(mvcResult -> System.out.println(mvcResult.getResponse().getContentAsString()))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("400"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("registration error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("bad pattern"));
}
@Test
public void postRegisterContextWithPersistenceException() throws Exception {
when(localRegistrations.updateRegistrationContext(any())).thenThrow(new RegistrationPersistenceException("Failed to save", new RuntimeException()));
mockMvc.perform(post("/v1/registerContext").content(json(mapper, createRegisterContextTemperature())).contentType(MediaType.APPLICATION_JSON))
.andDo(mvcResult -> System.out.println(mvcResult.getResponse().getContentAsString()))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("error in registration persistence"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("Failed to save"));
}
@Test
public void postNewRegisterContext() throws Exception {
when(localRegistrations.updateRegistrationContext(any())).thenReturn("12345678");
ListenableFuture<RegisterContextResponse> responseFuture = Mockito.mock(ListenableFuture.class);
doNothing().when(responseFuture).addCallback(any(), any());
when(ngsiClient.registerContext(any(), eq(null), any())).thenReturn(responseFuture);
mockMvc.perform(post("/v1/registerContext")
.content(json(mapper, createRegisterContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.registrationId").value("12345678"));
}
@Test
public void postUpdateContextWithNullUpdateAction() throws Exception {
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, new UpdateContext()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value(CodeEnum.CODE_471.getLabel()))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value(CodeEnum.CODE_471.getShortPhrase()))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("The parameter updateAction of type string is missing in the request"));
}
@Test
public void postUpdateContextWithoutProvidingApplication() throws Exception {
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(false);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
verify(configuration, atLeastOnce()).isRemoteForwardUpdateContext();
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
// Capture updateContext when postUpdateContextRequest is called on updateContextRequest,
ArgumentCaptor<UpdateContext> updateContextArg = ArgumentCaptor.forClass(UpdateContext.class);
String urlProvider = "http://orionhost:9999";
//check ListenableFuture is called at least Once and with addCallback method
verify(updateContextResponseListenableFuture, atLeastOnce()).addCallback(any(), any());
//check ngsiClient.getRequestHeaders() is called at least Once
verify(ngsiClient, atLeastOnce()).getRequestHeaders(eq("http://orionhost:9999"));
//check configuration.getHeadersForBroker() is called at least Once
verify(configuration, atLeastOnce()).addRemoteHeaders(any());
//verify urlProvider
verify(ngsiClient, atLeastOnce()).updateContext(eq(urlProvider), any(), updateContextArg.capture());
// Check id correspond to the required
ContextElement contextElement = updateContextArg.getValue().getContextElements().get(0);
assertEquals("S1", contextElement.getEntityId().getId());
//check ngsiClient.notify is not called
verify(ngsiClient, never()).notifyContext(any(), any(), any());
}
@Test
public void checkRemoteBrokerNotCalledWhenForwardIsDisabled() throws Exception {
// Disable updateContext forwarding to remote broker
when(configuration.isRemoteForwardUpdateContext()).thenReturn(false);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(false);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
verify(configuration, atLeastOnce()).isRemoteForwardUpdateContext();
verify(ngsiClient, never()).updateContext(eq("http://orionhost:9999"), any(), any());
}
@Test
public void postUpdateContextWithoutProvidingApplicationAndWithoutRemoteBrokerButWithNotify() throws Exception {
when(configuration.getRemoteUrl()).thenReturn(null);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always with matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true, false);
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("999999", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(matchedSubscriptions.next()).thenReturn(subscription);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//ngsiClient mock return always CODE_200
when(ngsiClient.notifyContextCustomURL(any(), any(), any())).thenReturn(notifyContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
//check ListenableFuture is called never and with addCallback method
verify(updateContextResponseListenableFuture, never()).addCallback(any(), any());
//verify ngsiClient.updateContext is never called
verify(ngsiClient, never()).updateContext(any(), any(), any());
//check ngsiClient.notify is called at least once
// Capture notifyContext when postNotifyContextRequest is called on updateContextRequest,
ArgumentCaptor<NotifyContext> notifyContextArg = ArgumentCaptor.forClass(NotifyContext.class);
verify(notifyContextResponseListenableFuture, atLeastOnce()).addCallback(any(), any());
String urlReference = subscribeContext.getReference().toString();
verify(ngsiClient, atLeastOnce()).notifyContextCustomURL(eq(urlReference), any(), notifyContextArg.capture());
// Check id and status correspond to the required
assertEquals(1, notifyContextArg.getValue().getContextElementResponseList().size());
ContextElementResponse contextElementResponse = notifyContextArg.getValue().getContextElementResponseList().get(0);
assertEquals("S1", contextElementResponse.getContextElement().getEntityId().getId());
assertEquals("200", contextElementResponse.getStatusCode().getCode());
}
@Test
public void postUpdateContextWithoutProvidingApplicationAndWithoutRemoteBrokerUrlButWithNotify() throws Exception {
when(configuration.getRemoteUrl()).thenReturn(null);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always with matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true, false);
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("999999", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(matchedSubscriptions.next()).thenReturn(subscription);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//ngsiClient mock return always CODE_200
when(ngsiClient.notifyContextCustomURL(any(), any(), any())).thenReturn(notifyContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
//check ListenableFuture is called never and with addCallback method
verify(updateContextResponseListenableFuture, never()).addCallback(any(), any());
//verify ngsiClient.updateContext is never called
verify(ngsiClient, never()).updateContext(any(), any(), any());
//check ngsiClient.notify is called at least once
// Capture notifyContext when postNotifyContextRequest is called on updateContextRequest,
ArgumentCaptor<NotifyContext> notifyContextArg = ArgumentCaptor.forClass(NotifyContext.class);
verify(notifyContextResponseListenableFuture, atLeastOnce()).addCallback(any(), any());
String urlReference = subscribeContext.getReference().toString();
verify(ngsiClient, atLeastOnce()).notifyContextCustomURL(eq(urlReference), any(), notifyContextArg.capture());
// Check id and status correspond to the required
assertEquals(1, notifyContextArg.getValue().getContextElementResponseList().size());
ContextElementResponse contextElementResponse = notifyContextArg.getValue().getContextElementResponseList().get(0);
assertEquals("S1", contextElementResponse.getContextElement().getEntityId().getId());
assertEquals("200", contextElementResponse.getStatusCode().getCode());
}
@Test
public void postUpdateContextWithoutProvidingApplicationAndWithEmptyRemoteBrokerButWithNotify() throws Exception {
when(configuration.getRemoteUrl()).thenReturn("");
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always with matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true, false);
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("999999", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(matchedSubscriptions.next()).thenReturn(subscription);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//ngsiClient mock return always CODE_200
when(ngsiClient.notifyContextCustomURL(any(), any(), any())).thenReturn(notifyContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
//check ListenableFuture is called never and with addCallback method
verify(updateContextResponseListenableFuture, never()).addCallback(any(), any());
//verify ngsiClient.updateContext is never called
verify(ngsiClient, never()).updateContext(any(), any(), any());
//check ngsiClient.notify is called at least once
// Capture notifyContext when postNotifyContextRequest is called on updateContextRequest,
ArgumentCaptor<NotifyContext> notifyContextArg = ArgumentCaptor.forClass(NotifyContext.class);
verify(notifyContextResponseListenableFuture, atLeastOnce()).addCallback(any(), any());
String urlReference = subscribeContext.getReference().toString();
verify(ngsiClient, atLeastOnce()).notifyContextCustomURL(eq(urlReference), any(), notifyContextArg.capture());
// Check id and status correspond to the required
assertEquals(1, notifyContextArg.getValue().getContextElementResponseList().size());
ContextElementResponse contextElementResponse = notifyContextArg.getValue().getContextElementResponseList().get(0);
assertEquals("S1", contextElementResponse.getContextElement().getEntityId().getId());
assertEquals("200", contextElementResponse.getStatusCode().getCode());
}
@Test
public void postUpdateContextWithoutProvidingApplicationAndWithoutRemoteBrokerButWithNullOriginator() throws Exception {
when(configuration.getRemoteUrl()).thenReturn(null);
when(configuration.getLocalUrl()).thenReturn(null);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always with matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true, false);
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("999999", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(matchedSubscriptions.next()).thenReturn(subscription);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//ngsiClient mock return always CODE_200
when(ngsiClient.notifyContextCustomURL(any(), any(), any())).thenReturn(notifyContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
//check ListenableFuture is called never and with addCallback method
verify(updateContextResponseListenableFuture, never()).addCallback(any(), any());
//verify ngsiClient.updateContext is never called
verify(ngsiClient, never()).updateContext(any(), any(), any());
//check ngsiClient.notify is never called
verify(notifyContextResponseListenableFuture, never()).addCallback(any(), any());
verify(ngsiClient, never()).notifyContext(any(), any(), any());
}
@Test
public void postUpdateContextWithoutProvidingApplicationAndWithoutRemoteBrokerButWithEmptyOriginator() throws Exception {
when(configuration.getRemoteUrl()).thenReturn(null);
when(configuration.getLocalUrl()).thenReturn("");
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always with matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true, false);
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("999999", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(matchedSubscriptions.next()).thenReturn(subscription);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//ngsiClient mock return always CODE_200
when(ngsiClient.notifyContext(any(), any(), any())).thenReturn(notifyContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
//check ListenableFuture is called never and with addCallback method
verify(updateContextResponseListenableFuture, never()).addCallback(any(), any());
//verify ngsiClient.updateContext is never called
verify(ngsiClient, never()).updateContext(any(), any(), any());
//check ngsiClient.notify is never called
verify(notifyContextResponseListenableFuture, never()).addCallback(any(), any());
verify(ngsiClient, never()).notifyContext(any(), any(), any());
}
@Test
public void postUpdateContextWithProvidingApplication() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(false);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
// Capture updateContext when updateContextRequest is called on updateContextRequest,
ArgumentCaptor<UpdateContext> updateContextArg = ArgumentCaptor.forClass(UpdateContext.class);
String urlProvider = "http//iotagent:1234";
//check ListenableFuture is called at least Once and with get method
verify(updateContextResponseListenableFuture, atLeastOnce()).get();
//verify urlProvider
verify(ngsiClient, atLeastOnce()).updateContext(eq(urlProvider), any(), updateContextArg.capture());
// Check id correspond to the required
ContextElement contextElement = updateContextArg.getValue().getContextElements().get(0);
assertEquals("S1", contextElement.getEntityId().getId());
//check ngsiClient.notify is not called
verify(ngsiClient, never()).notifyContext(any(), any(), any());
}
@Test
public void postUpdateContextWithProvidingApplicationAndMatchedSusbcriptions() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(true);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].name").value("pressure"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].type").value("int"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[1].value").value("1015"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S1", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertFalse(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(2, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
assertTrue(attributeArgumentCaptor.getValue().contains("pressure"));
// Capture updateContext when updateContextRequest is called on updateContextRequest,
ArgumentCaptor<UpdateContext> updateContextArg = ArgumentCaptor.forClass(UpdateContext.class);
String urlProvider = "http//iotagent:1234";
//check ListenableFuture is called at least Once and with get method
verify(updateContextResponseListenableFuture, atLeastOnce()).get();
//verify urlProvider
verify(ngsiClient, atLeastOnce()).updateContext(eq(urlProvider), any(), updateContextArg.capture());
// Check id correspond to the required
ContextElement contextElement = updateContextArg.getValue().getContextElements().get(0);
assertEquals("S1", contextElement.getEntityId().getId());
//check ngsiClient.notify is not called
verify(ngsiClient, never()).notifyContext(any(), any(), any());
}
@Test
public void postUpdateContextWithThrowExecutionException() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(false);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
when(updateContextResponseListenableFuture.get()).thenThrow(new ExecutionException("execution exception", new Throwable()));
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//check ngsiClient.notify is not called
verify(ngsiClient, never()).notifyContext(any(), any(), any());
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("Receiver internal error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("An unknown error at the receiver has occured"));
}
@Test
public void postUpdateContextWithThrowInterruptedException() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//subscriptions mock return always without matched subscriptions
when(matchedSubscriptions.hasNext()).thenReturn(false);
when(subscriptions.findSubscriptions(any(), any())).thenReturn(matchedSubscriptions);
when(updateContextResponseListenableFuture.get()).thenThrow(new InterruptedException());
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.updateContext(any(), any(), any())).thenReturn(updateContextResponseListenableFuture);
//check ngsiClient.notify is not called
verify(ngsiClient, never()).notifyContext(any(), any(), any());
mockMvc.perform(post("/v1/updateContext")
.content(json(mapper, createUpdateContextTempSensorAndPressure()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("Receiver internal error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("An unknown error at the receiver has occured"));
}
@Test
public void postQueryContextWithProvidingApplication() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createQueryContextResponseTemperature when call queryContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S*", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertTrue(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(1, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
// Capture queryContext when queryContextRequest is called on updateContextRequest,
ArgumentCaptor<QueryContext> queryContextArg = ArgumentCaptor.forClass(QueryContext.class);
String urlProvider = "http//iotagent:1234";
//check ListenableFuture is called at least Once and with get method
verify(queryContextResponseListenableFuture, atLeastOnce()).get();
//verify urlProvider
verify(ngsiClient, atLeastOnce()).queryContext(eq(urlProvider), any(), queryContextArg.capture());
// Check id correspond to the required
assertEquals(1, queryContextArg.getValue().getEntityIdList().size());
assertEquals("S*", queryContextArg.getValue().getEntityIdList().get(0).getId());
}
@Test
public void postQueryContextWithProvidingApplicationWithNullAttributes() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createQueryContextResponseTemperature when call queryContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
QueryContext queryContext = createQueryContextTemperature();
queryContext.setAttributeList(null);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, queryContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S*", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertTrue(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(0, attributeArgumentCaptor.getValue().size());
// Capture queryContext when queryContextRequest is called on queryContextRequest
ArgumentCaptor<QueryContext> queryContextArg = ArgumentCaptor.forClass(QueryContext.class);
String urlProvider = "http//iotagent:1234";
//check ListenableFuture is called at least Once and with get method
verify(queryContextResponseListenableFuture, atLeastOnce()).get();
//verify urlProvider
verify(ngsiClient, atLeastOnce()).queryContext(eq(urlProvider), any(), queryContextArg.capture());
// Check id correspond to the required
assertEquals(1, queryContextArg.getValue().getEntityIdList().size());
assertEquals("S*", queryContextArg.getValue().getEntityIdList().get(0).getId());
}
@Test
public void postQueryContextWithoutProvidingApplication() throws Exception {
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createQueryContextResponseTemperature when call queryContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode").doesNotExist())
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.id").value("S1"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.type").value("TempSensor"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].name").value("temp"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].type").value("float"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].contextElement.attributes[0].value").value("15.5"))
.andExpect(MockMvcResultMatchers.jsonPath("$.contextResponses[0].statusCode.code").value("200"));
//Capture attributes (Set<String> searchAttributes) when findProvidingApplication is called on localRegistrations Set<String> searchAttributes
verify(localRegistrations).findProvidingApplication(entityIdArgumentCaptor.capture(), attributeArgumentCaptor.capture());
//check entityId
assertEquals("S*", entityIdArgumentCaptor.getValue().getId());
assertEquals("TempSensor", entityIdArgumentCaptor.getValue().getType());
assertTrue(entityIdArgumentCaptor.getValue().getIsPattern());
//check attributes
assertEquals(1, attributeArgumentCaptor.getValue().size());
assertTrue(attributeArgumentCaptor.getValue().contains("temp"));
// Capture queryContext when queryContextRequest is called on updateContextRequest,
ArgumentCaptor<QueryContext> queryContextArg = ArgumentCaptor.forClass(QueryContext.class);
String urlProvider = "http://orionhost:9999";
// Capture HttpHeaders queryContextRequest is called on queryContextRequest
ArgumentCaptor<HttpHeaders> httpHeadersArg = ArgumentCaptor.forClass(HttpHeaders.class);
//check ListenableFuture is called at least Once and with get method
verify(queryContextResponseListenableFuture, atLeastOnce()).get();
//check ngsiClient.getRequestHeaders() is called at least Once
verify(ngsiClient, atLeastOnce()).getRequestHeaders(eq("http://orionhost:9999"));
//check configuration.getHeadersForBroker() is called at least Once
verify(configuration, atLeastOnce()).addRemoteHeaders(any());
//verify urlProvider
verify(ngsiClient, atLeastOnce()).queryContext(eq(urlProvider), httpHeadersArg.capture(), queryContextArg.capture());
// Check id correspond to the required
assertEquals(1, queryContextArg.getValue().getEntityIdList().size());
assertEquals("S*", queryContextArg.getValue().getEntityIdList().get(0).getId());
}
@Test
public void postQueryContextWithNullRemoteBroker() throws Exception {
//configuration mock return null as remoteBroker
when(configuration.getRemoteUrl()).thenReturn(null);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("missing remote broker error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("No remote.url parameter defined to forward queryContext"));
}
@Test
public void postQueryContextWithNullRemoteBrokerUrl() throws Exception {
//configuration mock return null as remoteBroker
when(configuration.getRemoteUrl()).thenReturn(null);
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("missing remote broker error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("No remote.url parameter defined to forward queryContext"));
}
@Test
public void postQueryContextWithEmptyRemoteBrokerUrl() throws Exception {
//configuration mock return "" as remoteBrokerUrl
when(configuration.getRemoteUrl()).thenReturn("");
//localRegistrations mock return always without providingApplication
when(providingApplication.hasNext()).thenReturn(false);
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("missing remote broker error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("No remote.url parameter defined to forward queryContext"));
}
@Test
public void postQueryContextWithExecutionException() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
when(queryContextResponseListenableFuture.get()).thenThrow(new ExecutionException("execution exception", new Throwable()));
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("Receiver internal error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("An unknown error at the receiver has occured"));
}
@Test
public void postQueryContextWithInterruptedException() throws Exception {
//localRegistrations mock return always a providingApplication
when(providingApplication.hasNext()).thenReturn(true);
when(providingApplication.next()).thenReturn(new URI("http//iotagent:1234"));
when(localRegistrations.findProvidingApplication(any(), any())).thenReturn(providingApplication);
when(queryContextResponseListenableFuture.get()).thenThrow(new InterruptedException());
//ngsiclient mock return always createUpdateContextREsponseTemperature when call updateContext
when(ngsiClient.queryContext(any(), any(), any())).thenReturn(queryContextResponseListenableFuture);
mockMvc.perform(post("/v1/queryContext")
.content(json(mapper, createQueryContextTemperature()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.reasonPhrase").value("Receiver internal error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.errorCode.details").value("An unknown error at the receiver has occured"));
}
@Test
public void postSubscribeContextWithEmptyEntities() throws Exception {
mockMvc.perform(post("/v1/subscribeContext")
.content(json(mapper, new SubscribeContext()))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.code").value(CodeEnum.CODE_471.getLabel()))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.reasonPhrase").value(CodeEnum.CODE_471.getShortPhrase()))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.details")
.value("The parameter entities of type List<EntityId> is missing in the request"));
}
@Test
public void postSubscribeContextWithBadDuration() throws Exception {
// Bad duration
SubscribeContext subscribeContext = createSubscribeContextTemperature();
subscribeContext.setDuration("PIPO");
when(subscriptions.addSubscription(any())).thenThrow(new SubscriptionException("bad duration", new RuntimeException()));
mockMvc.perform(post("/v1/subscribeContext")
.content(json(mapper, subscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.code").value("400"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.reasonPhrase").value("subscription error"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.details").value("bad duration"));
}
@Test
public void postNewSubscribeContext() throws Exception {
SubscribeContext subscribeContext = createSubscribeContextTemperature();
Subscription subscription = new Subscription("12345678", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContext);
when(subscriptions.addSubscription(any())).thenReturn("12345678");
when(subscriptions.getSubscription("12345678")).thenReturn(subscription);
mockMvc.perform(post("/v1/subscribeContext")
.content(json(mapper, subscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeResponse.subscriptionId").value("12345678"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeResponse.duration").value("P1M"));
verify(subscriptions, atLeastOnce()).addSubscription(any());
verify(subscriptions, atLeastOnce()).getSubscription("12345678");
}
@Test
public void postNewSubscribeContextWithNoDuration() throws Exception {
SubscribeContext subscribeContext = createSubscribeContextTemperature();
subscribeContext.setDuration(null);
SubscribeContext subscribeContextInSubscription = createSubscribeContextTemperature();
Subscription subscription = new Subscription("12345678", Instant.now().plus(1, ChronoUnit.DAYS), subscribeContextInSubscription);
when(subscriptions.addSubscription(any())).thenReturn("12345678");
when(subscriptions.getSubscription("12345678")).thenReturn(subscription);
mockMvc.perform(post("/v1/subscribeContext")
.content(json(mapper, subscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeResponse.subscriptionId").value("12345678"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeResponse.duration").value("P1M"));
verify(subscriptions, atLeastOnce()).addSubscription(any());
verify(subscriptions, atLeastOnce()).getSubscription("12345678");
}
@Test
public void postSubscribeContextWithPersistenceFailure() throws Exception {
SubscribeContext subscribeContext = createSubscribeContextTemperature();
when(subscriptions.addSubscription(any())).thenThrow(new SubscriptionPersistenceException("table not exist", new RuntimeException()));
mockMvc.perform(post("/v1/subscribeContext")
.content(json(mapper, subscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.code").value("500"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.reasonPhrase").value("error in subscription persistence"))
.andExpect(MockMvcResultMatchers.jsonPath("$.subscribeError.errorCode.details").value("table not exist"));
}
@Test
public void postUnSubscribeContextWhichExist() throws Exception {
UnsubscribeContext unsubscribeContext = new UnsubscribeContext("12345678");
when(subscriptions.deleteSubscription(any())).thenReturn(true);
mockMvc.perform(post("/v1/unsubscribeContext")
.content(json(mapper, unsubscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscriptionId").value("12345678"))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.code").value(CodeEnum.CODE_200.getLabel()));
verify(subscriptions, atLeastOnce()).deleteSubscription(any());
}
@Test
public void postUnSubscribeContextWhichNotExist() throws Exception {
UnsubscribeContext unsubscribeContext = new UnsubscribeContext("12345678");
when(subscriptions.deleteSubscription(any())).thenReturn(false);
mockMvc.perform(post("/v1/unsubscribeContext")
.content(json(mapper, unsubscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.subscriptionId").value("12345678"))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.code").value(CodeEnum.CODE_470.getLabel()))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.reasonPhrase").value(CodeEnum.CODE_470.getShortPhrase()))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.details").value("The subscription ID specified 12345678 does not correspond to an active subscription"));
verify(subscriptions, atLeastOnce()).deleteSubscription(any());
}
@Test
public void postUnSubscribeContextWithPersistenceFailure() throws Exception {
UnsubscribeContext unsubscribeContext = new UnsubscribeContext("12345678");
when(subscriptions.deleteSubscription(any())).thenThrow(new SubscriptionPersistenceException("table not exist", new RuntimeException()));
mockMvc.perform(post("/v1/unsubscribeContext")
.content(json(mapper, unsubscribeContext))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.code").value(CodeEnum.CODE_500.getLabel()))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.reasonPhrase").value("error in subscription persistence"))
.andExpect(MockMvcResultMatchers.jsonPath("$.statusCode.details").value("table not exist"));
verify(subscriptions, atLeastOnce()).deleteSubscription(any());
}
}