@Test
  public void testValidSubscription() {
    // add configuration
    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Capture the arg of subscription and return the mocked future
    ArgumentCaptor<String> urlProviderArg = ArgumentCaptor.forClass(String.class);
    ArgumentCaptor<SubscribeContext> subscribeContextArg =
        ArgumentCaptor.forClass(SubscribeContext.class);
    when(ngsiClient.subscribeContext(
            urlProviderArg.capture(), eq(null), subscribeContextArg.capture()))
        .thenReturn(responseFuture);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    // check ngsiClient.unsubscribe() is never called
    verify(ngsiClient, never()).unsubscribeContext(any(), any(), any());
    subscriptionManager.validateSubscriptionId("12345678", "http://iotAgent");
  }
  @Test
  public void testLoadEventsWithDecorators() {
    UUID identifier = UUID.randomUUID();
    SpyEventPreprocessor decorator1 = new SpyEventPreprocessor();
    SpyEventPreprocessor decorator2 = new SpyEventPreprocessor();
    testSubject.setEventStreamDecorators(Arrays.asList(decorator1, decorator2));
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 1, "Mock contents", MetaData.emptyInstance()),
                new GenericDomainEventMessage<String>(
                    identifier, (long) 2, "Mock contents", MetaData.emptyInstance()),
                new GenericDomainEventMessage<String>(
                    identifier, (long) 3, "Mock contents", MetaData.emptyInstance())));
    TestAggregate aggregate = testSubject.load(identifier);
    // loading them in...
    InOrder inOrder = Mockito.inOrder(decorator1.lastSpy, decorator2.lastSpy);
    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();

    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();

    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();
    aggregate.apply(new StubDomainEvent());
    aggregate.apply(new StubDomainEvent());
  }
  @Test
  public void setConfigurationOK() throws Exception {

    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Capture the arg of subscription and return the mocked future
    ArgumentCaptor<String> urlProviderArg = ArgumentCaptor.forClass(String.class);
    ArgumentCaptor<SubscribeContext> subscribeContextArg =
        ArgumentCaptor.forClass(SubscribeContext.class);
    when(ngsiClient.subscribeContext(
            urlProviderArg.capture(), eq(null), subscribeContextArg.capture()))
        .thenReturn(responseFuture);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    SubscribeContext subscribeContext = subscribeContextArg.getValue();
    assertEquals("S.*", subscribeContext.getEntityIdList().get(0).getId());
    assertEquals("TempSensor", subscribeContext.getEntityIdList().get(0).getType());
    assertEquals(true, subscribeContext.getEntityIdList().get(0).getIsPattern());
    assertEquals("temp", subscribeContext.getAttributeList().get(0));
    assertEquals("PT1H", subscribeContext.getDuration());
    assertEquals("http://iotAgent", urlProviderArg.getValue());

    Set<Provider> providers = configuration.getEventTypeIns().get(0).getProviders();
    for (Provider provider : providers) {
      assertEquals("12345678", provider.getSubscriptionId());
      assertNotNull(provider.getSubscriptionDate());
    }
  }
 @Test
 public void testInvalideSubscription() {
   // Mock future for unsubscribeContext
   ListenableFuture<UnsubscribeContextResponse> responseFuture =
       Mockito.mock(ListenableFuture.class);
   doNothing().when(responseFuture).addCallback(any(), any());
   when(ngsiClient.unsubscribeContext(eq("http://iotAgent"), eq(null), eq("9999")))
       .thenReturn(responseFuture);
   subscriptionManager.validateSubscriptionId("9999", "http://iotAgent");
 }
  @Test
  public void testUnsubscribeOnProviderRemoval() {

    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    // Return the mocked future on subscription
    when(ngsiClient.subscribeContext(any(), any(), any())).thenReturn(responseFuture);

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    // Mock future for unsubscribeContext
    ListenableFuture<UnsubscribeContextResponse> responseFuture2 =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture2).addCallback(successArg.capture(), any());
    when(ngsiClient.unsubscribeContext(eq("http://iotAgent"), eq(null), eq("12345678")))
        .thenReturn(responseFuture2);

    // Reset conf should trigger unsubsribeContext
    Configuration emptyConfiguration = getBasicConf();
    emptyConfiguration.getEventTypeIns().get(0).setProviders(Collections.emptySet());
    subscriptionManager.setConfiguration(emptyConfiguration);

    // Check that unsubsribe is called
    Assert.notNull(successArg.getValue());
  }
  @Test
  public void testSaveEventsWithDecorators() {
    SpyEventPreprocessor decorator1 = new SpyEventPreprocessor();
    SpyEventPreprocessor decorator2 = new SpyEventPreprocessor();
    testSubject.setEventStreamDecorators(Arrays.asList(decorator1, decorator2));
    testSubject.setEventStore(
        new EventStore() {
          @Override
          public void appendEvents(String type, DomainEventStream events) {
            while (events.hasNext()) {
              events.next();
            }
          }

          @Override
          public DomainEventStream readEvents(String type, Object identifier) {
            return mockEventStore.readEvents(type, identifier);
          }
        });
    UUID identifier = UUID.randomUUID();
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 3, "Mock contents", MetaData.emptyInstance())));
    TestAggregate aggregate = testSubject.load(identifier);
    aggregate.apply(new StubDomainEvent());
    aggregate.apply(new StubDomainEvent());

    CurrentUnitOfWork.commit();

    InOrder inOrder = Mockito.inOrder(decorator1.lastSpy, decorator2.lastSpy);
    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();

    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();
  }
/** Tests for SubscriptionManager */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class SubscriptionManagerTest {

  @Mock TaskScheduler taskScheduler;

  @Mock NgsiClient ngsiClient = Mockito.mock(NgsiClient.class, RETURNS_SMART_NULLS);

  @Autowired @InjectMocks SubscriptionManager subscriptionManager;

  @Before
  public void setUp() throws URISyntaxException {
    MockitoAnnotations.initMocks(this);
  }

  @After
  public void after() {
    reset(ngsiClient);
    reset(taskScheduler);
  }

  @Test
  public void setConfigurationOK() throws Exception {

    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Capture the arg of subscription and return the mocked future
    ArgumentCaptor<String> urlProviderArg = ArgumentCaptor.forClass(String.class);
    ArgumentCaptor<SubscribeContext> subscribeContextArg =
        ArgumentCaptor.forClass(SubscribeContext.class);
    when(ngsiClient.subscribeContext(
            urlProviderArg.capture(), eq(null), subscribeContextArg.capture()))
        .thenReturn(responseFuture);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    SubscribeContext subscribeContext = subscribeContextArg.getValue();
    assertEquals("S.*", subscribeContext.getEntityIdList().get(0).getId());
    assertEquals("TempSensor", subscribeContext.getEntityIdList().get(0).getType());
    assertEquals(true, subscribeContext.getEntityIdList().get(0).getIsPattern());
    assertEquals("temp", subscribeContext.getAttributeList().get(0));
    assertEquals("PT1H", subscribeContext.getDuration());
    assertEquals("http://iotAgent", urlProviderArg.getValue());

    Set<Provider> providers = configuration.getEventTypeIns().get(0).getProviders();
    for (Provider provider : providers) {
      assertEquals("12345678", provider.getSubscriptionId());
      assertNotNull(provider.getSubscriptionDate());
    }
  }

  @Test
  public void testUnsubscribeOnEventTypeRemoval() {

    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    // Return the mocked future on subscription
    when(ngsiClient.subscribeContext(any(), any(), any())).thenReturn(responseFuture);

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    // Mock future for unsubscribeContext
    ListenableFuture<UnsubscribeContextResponse> responseFuture2 =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture2).addCallback(successArg.capture(), any());
    when(ngsiClient.unsubscribeContext(eq("http://iotAgent"), eq(null), eq("12345678")))
        .thenReturn(responseFuture2);

    // Set a configuration without the eventType
    Configuration emptyConfiguration = new Configuration();
    emptyConfiguration.setEventTypeIns(Collections.emptyList());
    subscriptionManager.setConfiguration(emptyConfiguration);

    // Check that unsubsribe is called when a later configuration removed the event type
    Assert.notNull(successArg.getValue());
  }

  @Test
  public void testUnsubscribeOnProviderRemoval() {

    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    // Return the mocked future on subscription
    when(ngsiClient.subscribeContext(any(), any(), any())).thenReturn(responseFuture);

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    // Mock future for unsubscribeContext
    ListenableFuture<UnsubscribeContextResponse> responseFuture2 =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture2).addCallback(successArg.capture(), any());
    when(ngsiClient.unsubscribeContext(eq("http://iotAgent"), eq(null), eq("12345678")))
        .thenReturn(responseFuture2);

    // Reset conf should trigger unsubsribeContext
    Configuration emptyConfiguration = getBasicConf();
    emptyConfiguration.getEventTypeIns().get(0).setProviders(Collections.emptySet());
    subscriptionManager.setConfiguration(emptyConfiguration);

    // Check that unsubsribe is called
    Assert.notNull(successArg.getValue());
  }

  @Test
  public void testInvalideSubscription() {
    // Mock future for unsubscribeContext
    ListenableFuture<UnsubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(any(), any());
    when(ngsiClient.unsubscribeContext(eq("http://iotAgent"), eq(null), eq("9999")))
        .thenReturn(responseFuture);
    subscriptionManager.validateSubscriptionId("9999", "http://iotAgent");
  }

  @Test
  public void testValidSubscription() {
    // add configuration
    // Mock the task scheduler and capture the runnable
    ArgumentCaptor<Runnable> runnableArg = ArgumentCaptor.forClass(Runnable.class);
    when(taskScheduler.scheduleWithFixedDelay(runnableArg.capture(), anyLong()))
        .thenReturn(Mockito.mock(ScheduledFuture.class));

    // Mock the response to the subsribeContext
    ArgumentCaptor<SuccessCallback> successArg = ArgumentCaptor.forClass(SuccessCallback.class);
    ListenableFuture<SubscribeContextResponse> responseFuture =
        Mockito.mock(ListenableFuture.class);
    doNothing().when(responseFuture).addCallback(successArg.capture(), any());

    Configuration configuration = getBasicConf();
    subscriptionManager.setConfiguration(configuration);

    // Capture the arg of subscription and return the mocked future
    ArgumentCaptor<String> urlProviderArg = ArgumentCaptor.forClass(String.class);
    ArgumentCaptor<SubscribeContext> subscribeContextArg =
        ArgumentCaptor.forClass(SubscribeContext.class);
    when(ngsiClient.subscribeContext(
            urlProviderArg.capture(), eq(null), subscribeContextArg.capture()))
        .thenReturn(responseFuture);

    // Execute scheduled runnable
    runnableArg.getValue().run();

    // Return the SubscribeContextResponse
    callSuccessCallback(successArg);

    // check ngsiClient.unsubscribe() is never called
    verify(ngsiClient, never()).unsubscribeContext(any(), any(), any());
    subscriptionManager.validateSubscriptionId("12345678", "http://iotAgent");
  }

  private void callSuccessCallback(ArgumentCaptor<SuccessCallback> successArg) {
    SubscribeContextResponse response = new SubscribeContextResponse();
    SubscribeResponse subscribeResponse = new SubscribeResponse();
    subscribeResponse.setSubscriptionId("12345678");
    subscribeResponse.setDuration("PT1H");
    response.setSubscribeResponse(subscribeResponse);
    successArg.getValue().onSuccess(response);
  }
}