/* * 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; import com.orange.cepheus.broker.exception.SubscriptionException; import com.orange.cepheus.broker.exception.SubscriptionPersistenceException; import com.orange.cepheus.broker.model.Subscription; import com.orange.cepheus.broker.persistence.SubscriptionsRepository; 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.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Assert; import org.junit.Rule; import org.junit.rules.ExpectedException; import java.net.URI; import java.net.URISyntaxException; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import static com.orange.cepheus.broker.Util.createSubscribeContext; import static com.orange.cepheus.broker.Util.createSubscribeContextTemperature; import static org.junit.Assert.*; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import static org.mockito.Matchers.any; /** * Tests for Subscriptions management */ @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @TestPropertySource(locations="classpath:test.properties") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class SubscriptionsTest { @Rule public ExpectedException thrown= ExpectedException.none(); @Autowired public Subscriptions subscriptions; @Autowired SubscriptionsRepository subscriptionsRepository; @Test public void addSubscriptionTest() throws URISyntaxException, SubscriptionException, SubscriptionPersistenceException { SubscribeContext subscribeContext = createSubscribeContextTemperature(); String subscriptionId = subscriptions.addSubscription(subscribeContext); Assert.notNull(subscriptionId); Assert.hasLength(subscriptionId); Assert.notNull(subscriptions.getSubscription(subscriptionId)); Map<String, Subscription> subscriptions = subscriptionsRepository.getAllSubscriptions(); Assert.isTrue(subscriptions.size()==1); Assert.notNull(subscriptions.get(subscriptionId).getExpirationDate()); } @Test public void addSubscriptionWithNegativeDurationTest() throws SubscriptionException, URISyntaxException, SubscriptionPersistenceException { thrown.expect(SubscriptionException.class); thrown.expectMessage("negative duration is not allowed"); SubscribeContext subscribeContext = createSubscribeContextTemperature(); subscribeContext.setDuration("-PT10S"); subscriptions.addSubscription(subscribeContext); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==0); } @Test public void addSubscriptionWithBadDurationTest() throws SubscriptionException, URISyntaxException, SubscriptionPersistenceException { thrown.expect(SubscriptionException.class); thrown.expectMessage("bad duration: PIPO"); SubscribeContext subscribeContext = createSubscribeContextTemperature(); subscribeContext.setDuration("PIPO"); subscriptions.addSubscription(subscribeContext); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==0); } @Test public void addSubscriptionWithZeroDurationTest() throws SubscriptionException, URISyntaxException, SubscriptionPersistenceException { SubscribeContext subscribeContext = createSubscribeContextTemperature(); subscribeContext.setDuration("PT0S"); String subscriptionId = subscriptions.addSubscription(subscribeContext); Assert.notNull(subscriptionId); Assert.hasLength(subscriptionId); Subscription subscription = subscriptions.getSubscription(subscriptionId); Assert.notNull(subscription); Assert.notNull(subscription.getExpirationDate()); Assert.notNull(subscription.getSubscriptionId()); assertEquals(subscriptionId, subscription.getSubscriptionId()); Calendar c = (Calendar) Calendar.getInstance().clone(); c.add(Calendar.MONTH, 1); c.add(Calendar.HOUR, 24); assertFalse(subscription.getExpirationDate().isAfter(c.toInstant())); c.add(Calendar.HOUR, -48); assertFalse(subscription.getExpirationDate().isBefore(c.toInstant())); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==1); } @Test public void addSubscriptionWithBadPatternTest() throws SubscriptionException, URISyntaxException, SubscriptionPersistenceException { thrown.expect(SubscriptionException.class); thrown.expectMessage("bad pattern"); SubscribeContext subscribeContext = createSubscribeContextTemperature(); subscribeContext.getEntityIdList().get(0).setId("]|,\\(("); subscribeContext.getEntityIdList().get(0).setIsPattern(true); subscriptions.addSubscription(subscribeContext); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==0); } @Test public void deleteExistSubscriptions() throws URISyntaxException, SubscriptionException, SubscriptionPersistenceException { SubscribeContext subscribeContext = createSubscribeContextTemperature(); String subscriptionId = subscriptions.addSubscription(subscribeContext); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==1); UnsubscribeContext unsubscribeContext = new UnsubscribeContext(subscriptionId); assertTrue(subscriptions.deleteSubscription(unsubscribeContext)); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==0); } @Test public void deleteNotExistSubscriptions() throws URISyntaxException, SubscriptionException, SubscriptionPersistenceException { UnsubscribeContext unsubscribeContext = new UnsubscribeContext("12345"); assertFalse(subscriptions.deleteSubscription(unsubscribeContext)); } @Test public void purgeExpiredSubscriptionsTest() throws URISyntaxException, SubscriptionException, InterruptedException, SubscriptionPersistenceException { SubscribeContext subscribeContext = createSubscribeContextTemperature(); subscribeContext.setDuration("PT1S"); // 1s only String subscriptionId = subscriptions.addSubscription(subscribeContext); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==1); Thread.sleep(1500); subscriptions.purgeExpiredSubscriptions(); assertNull(subscriptions.getSubscription(subscriptionId)); Assert.isTrue(subscriptionsRepository.getAllSubscriptions().size()==0); } @Test public void testFindEntityId() throws Exception { // Insert 3 subscriptions for (String n : new String[]{"A", "B", "C"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n, "temp")); } // Find B EntityId searchedEntityId = new EntityId("B", "string", false); Iterator<Subscription> it = subscriptions.findSubscriptions(searchedEntityId, null); assertTrue(it.hasNext()); assertEquals("http://B", it.next().getSubscribeContext().getReference().toString()); assertFalse(it.hasNext()); } @Test public void testFindEntityIds() throws Exception { // Insert 3 subscriptions for (String n : new String[]{"A", "B", "C"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n, "temp")); } // Insert 3 more for (String n : new String[]{"A", "B", "C"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n + "2", "temp")); } // Find the two B EntityId searchedEntityId = new EntityId("B", "string", false); List<String> results = new LinkedList<>(); subscriptions.findSubscriptions(searchedEntityId, null).forEachRemaining(subscription -> results.add(subscription.getSubscribeContext().getReference().toString())); Collections.sort(results); assertEquals(2, results.size()); assertEquals("http://B", results.get(0)); assertEquals("http://B2", results.get(1)); } @Test public void testFindEntityIdPattern() throws Exception { // Insert 3 localRegistrations for (String n : new String[]{"A", "B", "C"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n, "temp")); } // Find A and B EntityId searchedEntityId = new EntityId("A|B", "string", true); List<String> results = new LinkedList<>(); subscriptions.findSubscriptions(searchedEntityId, null).forEachRemaining(subscription -> results.add(subscription.getSubscribeContext().getReference().toString())); Collections.sort(results); assertEquals(2, results.size()); assertEquals("http://A", results.get(0)); assertEquals("http://B", results.get(1)); } @Test public void testFindEntityIdPattern2() throws Exception { // Insert 3 subscriptions subscriptions.addSubscription(createSubscribeContext("A|B", "string", true, "http://" + "AB", "temp")); for (String n : new String[]{"C", "D"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n, "temp")); } // Find A and B EntityId searchedEntityId = new EntityId("A", "string", false); List<String> results = new LinkedList<>(); subscriptions.findSubscriptions(searchedEntityId, null).forEachRemaining(subscription -> results.add(subscription.getSubscribeContext().getReference().toString())); Collections.sort(results); assertEquals(1, results.size()); assertEquals("http://AB", results.get(0)); } @Test public void testPartialAttributesMatch() throws Exception { SubscribeContext subscribeContext = createSubscribeContext("A", "string", false, "http://A" , ""); subscribeContext.setAttributeList(Arrays.asList("temp", "humidity")); subscriptions.addSubscription(subscribeContext); // Find http://A matching temp Iterator<Subscription> it = subscriptions.findSubscriptions(new EntityId("A", "string", false), new HashSet<>(Arrays.asList("temp"))); assertTrue(it.hasNext()); assertEquals("http://A", it.next().getSubscribeContext().getReference().toString()); assertFalse(it.hasNext()); // Find http://A matching humidity and temp it = subscriptions.findSubscriptions(new EntityId("A", "string", false), new HashSet<>(Arrays.asList("humidity", "temp"))); assertTrue(it.hasNext()); assertEquals("http://A", it.next().getSubscribeContext().getReference().toString()); assertFalse(it.hasNext()); // Find http://A matching humidity it = subscriptions.findSubscriptions(new EntityId("A", "string", false), new HashSet<>(Arrays.asList("humidity", "pressure"))); assertTrue(it.hasNext()); assertEquals("http://A", it.next().getSubscribeContext().getReference().toString()); assertFalse(it.hasNext()); } @Test public void testFindEntityIdNoMatch() throws Exception { // Insert 3 subscriptions for (String n : new String[]{"A", "B", "C"}) { subscriptions.addSubscription(createSubscribeContext(n, "string", false, "http://" + n, "temp")); } EntityId searchedEntityId = new EntityId("D", "string", false); Iterator<Subscription> it = subscriptions.findSubscriptions(searchedEntityId, null); assertFalse(it.hasNext()); searchedEntityId = new EntityId("B", "wrongtype", false); it = subscriptions.findSubscriptions(searchedEntityId, null); assertFalse(it.hasNext()); } @Test public void testFindEntityIdExpired() throws Exception { // Insert 3 localRegistrations with short expiration for (String n : new String[]{"A", "B", "C"}) { SubscribeContext subscribeContext = createSubscribeContext(n, "string", false, "http://" + n, "temp"); subscribeContext.setDuration("PT1S"); subscriptions.addSubscription(subscribeContext); } // Wait for expiration Thread.sleep(1500); EntityId searchedEntityId = new EntityId("A", "string", false); Iterator<Subscription> it = subscriptions.findSubscriptions(searchedEntityId, null); assertFalse(it.hasNext()); searchedEntityId = new EntityId("B", "string", false); it = subscriptions.findSubscriptions(searchedEntityId, null); assertFalse(it.hasNext()); searchedEntityId = new EntityId("C", "string", false); it = subscriptions.findSubscriptions(searchedEntityId, null); assertFalse(it.hasNext()); } }