/*
* Copyright 2014-2016 CyberVision, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaaproject.kaa.client.notification;
import static org.mockito.Mockito.mock;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kaaproject.kaa.client.KaaClientProperties;
import org.kaaproject.kaa.client.channel.NotificationTransport;
import org.kaaproject.kaa.client.context.ExecutorContext;
import org.kaaproject.kaa.client.persistance.KaaClientPropertiesStateTest;
import org.kaaproject.kaa.client.persistence.FilePersistentStorage;
import org.kaaproject.kaa.client.persistence.KaaClientPropertiesState;
import org.kaaproject.kaa.client.util.CommonsBase64;
import org.kaaproject.kaa.common.avro.AvroByteArrayConverter;
import org.kaaproject.kaa.common.endpoint.gen.Notification;
import org.kaaproject.kaa.common.endpoint.gen.NotificationType;
import org.kaaproject.kaa.common.endpoint.gen.SubscriptionType;
import org.kaaproject.kaa.common.endpoint.gen.Topic;
import org.mockito.Mockito;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class DefaultNotificationManagerTest {
private static final String workDir = "work_dir" + System.getProperty("file.separator");
private static final Long UNKNOWN_TOPIC_ID = 100500l;
private static ExecutorContext executorContext;
private static ExecutorService executor;
@BeforeClass
public static void beforeSuite() {
executorContext = Mockito.mock(ExecutorContext.class);
executor = Executors.newSingleThreadExecutor();
Mockito.when(executorContext.getApiExecutor()).thenReturn(executor);
Mockito.when(executorContext.getCallbackExecutor()).thenReturn(executor);
}
@AfterClass
public static void afterSuite() {
executor.shutdown();
}
@Test
public void testEmptyTopicList() throws IOException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
for (Topic t : notificationManager.getTopics()) {
System.out.println(t);
}
Assert.assertTrue(notificationManager.getTopics().isEmpty());
}
@Test
public void testTopicsAfterUpdate() throws IOException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topics = Arrays.asList(new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topics);
Assert.assertTrue(notificationManager.getTopics().size() == topics.size());
}
@Test
public void testTopicPersistence() throws IOException {
KaaClientProperties props = KaaClientPropertiesStateTest.getProperties();
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), props);
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topics = Arrays.asList(new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topics);
state.persist();
KaaClientPropertiesState newState = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
DefaultNotificationManager newNotificationManager = new DefaultNotificationManager(newState, executorContext, transport);
Assert.assertTrue(newNotificationManager.getTopics().size() == topics.size());
boolean deleted = new File(workDir + props.getProperty("state.file_name")).delete();
Assert.assertTrue(deleted);
}
@Test
public void testTwiceTopicUpdate() throws IOException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
Topic topic1 = new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION);
Topic topic2 = new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION);
Topic topic3 = new Topic(3l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION);
List<Topic> topicUpdates = new LinkedList<>();
topicUpdates.add(topic1);
topicUpdates.add(topic2);
notificationManager.topicsListUpdated(topicUpdates);
topicUpdates.remove(topic2);
topicUpdates.add(topic3);
notificationManager.topicsListUpdated(topicUpdates);
List<Topic> newTopics = notificationManager.getTopics();
Assert.assertTrue(newTopics.size() == topicUpdates.size());
Assert.assertTrue(newTopics.contains(topic1));
Assert.assertTrue(newTopics.contains(topic3));
}
@Test
public void testAddTopicUpdateListener() throws Exception {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
final List<Topic> topicUpdates = new LinkedList<>();
topicUpdates.add(new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
topicUpdates.add(new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
topicUpdates.add(new Topic(3l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.addTopicListListener(new NotificationTopicListListener() {
@Override
public void onListUpdated(List<Topic> list) {
Assert.assertArrayEquals(topicUpdates.toArray(), list.toArray());
topicUpdates.clear();
}
});
notificationManager.topicsListUpdated(topicUpdates);
Thread.sleep(500);
Assert.assertTrue(topicUpdates.isEmpty());
}
@Test
public void testRemoveTopicUpdateListener() throws IOException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
NotificationTopicListListener listener1 = Mockito.mock(NotificationTopicListListener.class);
NotificationTopicListListener listener2 = Mockito.mock(NotificationTopicListListener.class);
notificationManager.addTopicListListener(listener1);
notificationManager.addTopicListListener(listener2);
List<Topic> topicUpdate = Arrays.asList(new Topic());
notificationManager.topicsListUpdated(topicUpdate);
notificationManager.removeTopicListListener(listener2);
notificationManager.topicsListUpdated(topicUpdate);
Mockito.verify(listener1, Mockito.timeout(1000).times(2)).onListUpdated(topicUpdate);
Mockito.verify(listener2, Mockito.timeout(1000).times(1)).onListUpdated(topicUpdate);
}
@Test
public void testGlobalNotificationListeners() throws Exception {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
ByteBuffer notificationBody = ByteBuffer.wrap(new AvroByteArrayConverter<>(org.kaaproject.kaa.schema.base.Notification.class).toByteArray(
new org.kaaproject.kaa.schema.base.Notification()));
notificationManager.topicsListUpdated(topicsUpdate);
List<Notification> notificationUpdate = Arrays.asList(
new Notification(1l, NotificationType.CUSTOM, null, 1, notificationBody),
new Notification(2l, NotificationType.CUSTOM, null, 1, notificationBody));
NotificationListener mandatoryListener = Mockito.mock(NotificationListener.class);
NotificationListener globalListener = Mockito.mock(NotificationListener.class);
notificationManager.addNotificationListener(mandatoryListener);
notificationManager.notificationReceived(notificationUpdate);
Thread.sleep(500);
notificationManager.removeNotificationListener(mandatoryListener);
notificationManager.addNotificationListener(globalListener);
notificationManager.notificationReceived(notificationUpdate);
notificationManager.notificationReceived(notificationUpdate);
Mockito.verify(mandatoryListener, Mockito.timeout(1000).times(notificationUpdate.size()))
.onNotification(Mockito.anyLong(), Mockito.any(org.kaaproject.kaa.schema.base.Notification.class));
Mockito.verify(globalListener, Mockito.timeout(1000).times(notificationUpdate.size() * 2))
.onNotification(Mockito.anyLong(), Mockito.any(org.kaaproject.kaa.schema.base.Notification.class));
}
@Test
public void testNotificationListenerOnTopic() throws Exception {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
ByteBuffer notificationBody = ByteBuffer.wrap(new AvroByteArrayConverter<>(Topic.class).toByteArray(
new Topic(3l, "name", SubscriptionType.MANDATORY_SUBSCRIPTION)));
notificationManager.topicsListUpdated(topicsUpdate);
List<Notification> notificationUpdate = Arrays.asList(
new Notification(1l, NotificationType.CUSTOM, null, 1, notificationBody),
new Notification(2l, NotificationType.CUSTOM, null, 1, notificationBody));
NotificationListener globalListener = Mockito.mock(NotificationListener.class);
NotificationListener topicListener = Mockito.mock(NotificationListener.class);
notificationManager.addNotificationListener(globalListener);
notificationManager.addNotificationListener(2l, topicListener);
notificationManager.notificationReceived(notificationUpdate);
notificationManager.removeNotificationListener(2l, topicListener);
notificationManager.notificationReceived(notificationUpdate);
Mockito.verify(globalListener, Mockito.timeout(1000).times(notificationUpdate.size() * 2 - 1))
.onNotification(Mockito.anyLong(), Mockito.any(org.kaaproject.kaa.schema.base.Notification.class));
Mockito.verify(topicListener, Mockito.timeout(1000).times(1))
.onNotification(Mockito.anyLong(), Mockito.any(org.kaaproject.kaa.schema.base.Notification.class));
}
@Test(expected = UnavailableTopicException.class)
public void testAddListenerForUnknownTopic() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
NotificationListener listener = Mockito.mock(NotificationListener.class);
notificationManager.addNotificationListener(UNKNOWN_TOPIC_ID, listener);
}
@Test(expected = UnavailableTopicException.class)
public void testRemoveListenerForUnknownTopic() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
NotificationListener listener = Mockito.mock(NotificationListener.class);
notificationManager.removeNotificationListener(UNKNOWN_TOPIC_ID, listener);
}
@Test(expected = UnavailableTopicException.class)
public void testSubscribeOnUnknownTopic1() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.subscribeToTopic(UNKNOWN_TOPIC_ID, true);
}
@Test(expected = UnavailableTopicException.class)
public void testSubscribeOnUnknownTopic2() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.subscribeToTopics(Arrays.asList(1l, 2l, UNKNOWN_TOPIC_ID), true);
}
@Test(expected = UnavailableTopicException.class)
public void testUnsubscribeFromUnknownTopic1() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.unsubscribeFromTopic(UNKNOWN_TOPIC_ID, true);
}
@Test(expected = UnavailableTopicException.class)
public void testUnsubscribeFromUnknownTopic2() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.unsubscribeFromTopics(Arrays.asList(1l, 2l, UNKNOWN_TOPIC_ID), true);
}
@Test(expected = UnavailableTopicException.class)
public void testSubscribeOnMandatoryTopic1() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.subscribeToTopic(2l, true);
}
@Test(expected = UnavailableTopicException.class)
public void testSubscribeOnMandatoryTopic2() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.subscribeToTopics(Arrays.asList(1l, 2l), true);
}
@Test(expected = UnavailableTopicException.class)
public void testUnsubscribeFromMandatoryTopic1() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.unsubscribeFromTopic(2l, true);
}
@Test(expected = UnavailableTopicException.class)
public void testUnsubscribeFromMandatoryTopic2() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.MANDATORY_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.unsubscribeFromTopics(Arrays.asList(1l, 2l), true);
}
@Test
public void testSuccessSubscriptionToTopic() throws IOException, UnavailableTopicException {
KaaClientPropertiesState state = new KaaClientPropertiesState(
new FilePersistentStorage(), CommonsBase64.getInstance(), KaaClientPropertiesStateTest.getProperties());
NotificationTransport transport = mock(NotificationTransport.class);
DefaultNotificationManager notificationManager = new DefaultNotificationManager(state, executorContext, transport);
List<Topic> topicsUpdate = Arrays.asList(
new Topic(1l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(2l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION)
, new Topic(3l, "topic_name1", SubscriptionType.OPTIONAL_SUBSCRIPTION));
notificationManager.topicsListUpdated(topicsUpdate);
notificationManager.subscribeToTopic(1l, true);
Mockito.verify(transport, Mockito.times(1)).sync();
notificationManager.subscribeToTopics(Arrays.asList(1l, 2l), false);
notificationManager.unsubscribeFromTopic(1l, false);
Mockito.verify(transport, Mockito.times(1)).sync();
notificationManager.sync();
Mockito.verify(transport, Mockito.times(2)).sync();
notificationManager.unsubscribeFromTopics(Arrays.asList(1l, 2l), true);
Mockito.verify(transport, Mockito.times(3)).sync();
}
}