Removed all the old ProtocolProcessor stuff

This commit is contained in:
andsel
2018-11-08 22:18:11 +01:00
parent 24e9d9f83c
commit e10619813a
79 changed files with 483 additions and 6043 deletions
@@ -12,7 +12,7 @@ import java.util.List;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED;
import static org.junit.Assert.*;
class ConnectionTestUtils {
public class ConnectionTestUtils {
public static final List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList();
public static final BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS);
@@ -1,9 +1,6 @@
package io.moquette.broker;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -49,13 +46,11 @@ public class MQTTConnectionPublishTest {
}
private MQTTConnection createMQTTConnection(BrokerConfiguration config, Channel channel) {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
IAuthenticator mockAuthenticator = new MockAuthenticator(singleton(FAKE_CLIENT_ID), singletonMap(TEST_USER, TEST_PWD));
ISubscriptionsDirectory subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
sessionRegistry = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
final PostOffice postOffice = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(),
@@ -1,9 +1,6 @@
package io.moquette.broker;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -66,12 +63,9 @@ public class PostOfficeInternalPublishTest {
}
private SessionRegistry initPostOfficeAndSubsystems() {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
retainedRepository = new MemoryRetainedRepository();
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
@@ -1,9 +1,6 @@
package io.moquette.broker;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -73,12 +70,9 @@ public class PostOfficePublishTest {
}
private SessionRegistry initPostOfficeAndSubsystems() {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
retainedRepository = new MemoryRetainedRepository();
SessionRegistry sessionRegistry = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
@@ -114,7 +108,7 @@ public class PostOfficePublishTest {
.payload(anyPayload)
.qos(MqttQoS.EXACTLY_ONCE)
.retained(false)
.topicName(NEWS_TOPIC).build());
.topicName(NEWS_TOPIC).build(), "username");
final MQTTConnection clientYA = connectAs("subscriber");
subscribe(clientYA, NEWS_TOPIC, AT_MOST_ONCE);
@@ -125,7 +119,7 @@ public class PostOfficePublishTest {
.payload(anyPayload2)
.qos(MqttQoS.EXACTLY_ONCE)
.retained(true)
.topicName(NEWS_TOPIC).build());
.topicName(NEWS_TOPIC).build(), "username");
// Verify
assertFalse("First 'subscriber' channel MUST be closed by the broker", clientXA.channel.isOpen());
@@ -249,7 +243,7 @@ public class PostOfficePublishTest {
.payload(anyPayload)
.qos(MqttQoS.EXACTLY_ONCE)
.retained(true)
.topicName(NEWS_TOPIC).build());
.topicName(NEWS_TOPIC).build(), "username");
// Verify
ConnectionTestUtils.verifyPublishIsReceived(channel, EXACTLY_ONCE, "Any payload");
@@ -4,7 +4,6 @@ import io.moquette.persistence.MemoryStorageService;
import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -71,13 +70,11 @@ public class PostOfficeSubscribeTest {
}
private void prepareSUT() {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
mockAuthenticator = new MockAuthenticator(singleton(FAKE_CLIENT_ID), singletonMap(TEST_USER, TEST_PWD));
subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
sessionRegistry = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), new MemoryRetainedRepository(),
@@ -1,9 +1,6 @@
package io.moquette.broker;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -61,13 +58,11 @@ public class PostOfficeUnsubscribeTest {
}
private void prepareSUT() {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
mockAuthenticator = new MockAuthenticator(singleton(FAKE_CLIENT_ID), singletonMap(TEST_USER, TEST_PWD));
subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
sessionRegistry = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
sut = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(), new MemoryRetainedRepository(),
@@ -308,7 +303,7 @@ public class PostOfficeUnsubscribeTest {
.payload(bytePayload)
.qos(MqttQoS.EXACTLY_ONCE)
.retained(true)
.topicName(NEWS_TOPIC).build());
.topicName(NEWS_TOPIC).build(), "username");
}
/**
@@ -4,7 +4,6 @@ import io.moquette.persistence.MemoryStorageService;
import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.MockAuthenticator;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
@@ -61,13 +60,11 @@ public class SessionRegistryTest {
}
private MQTTConnection createMQTTConnection(BrokerConfiguration config, Channel channel) {
MemoryStorageService memStorage = new MemoryStorageService(null, null);
ISessionsStore sessionStore = memStorage.sessionsStore();
IAuthenticator mockAuthenticator = new MockAuthenticator(singleton(FAKE_CLIENT_ID), singletonMap(TEST_USER, TEST_PWD));
ISubscriptionsDirectory subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
ISubscriptionsRepository subscriptionsRepository = new MemorySubscriptionsRepository();
subscriptions.init(subscriptionsRepository);
sut = new SessionRegistry(subscriptions, ConnectionTestUtils.NO_OBSERVERS_INTERCEPTOR);
final PostOffice postOffice = new PostOffice(subscriptions, new PermitAllAuthorizatorPolicy(),
@@ -1,112 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.persistence;
import io.moquette.spi.*;
import io.moquette.spi.IMessagesStore.StoredMessage;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.subscriptions.Subscription;
import io.moquette.spi.impl.subscriptions.Topic;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static io.moquette.spi.impl.subscriptions.Topic.asTopic;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
import static io.netty.handler.codec.mqtt.MqttQoS.EXACTLY_ONCE;
import static java.nio.charset.StandardCharsets.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Defines all test that an implementation of a IMessageStore should satisfy.
* */
public abstract class MessageStoreTCK {
public static final String TEST_CLIENT = "TestClient";
protected ISessionsStore sessionsStore;
protected IMessagesStore messagesStore;
protected SessionsRepository sessionsRepository;
@Test
public void testDropMessagesInSessionDoesntCleanAnyRetainedStoredMessages() throws UnsupportedEncodingException {
final ClientSession session = sessionsRepository.createNewSession(TEST_CLIENT, true);
StoredMessage publishToStore = new StoredMessage("Hello".getBytes(UTF_8), EXACTLY_ONCE, "/topic");
publishToStore.setClientID(TEST_CLIENT);
publishToStore.setRetained(true);
messagesStore.storeRetained(new Topic("/topic"), publishToStore);
// Exercise
session.cleanSession();
// Verify the message store for session is empty.
StoredMessage storedPublish = messagesStore.searchMatching(new IMatchingCondition() {
@Override
public boolean match(Topic key) {
return key.match(new Topic("/topic"));
}
}).iterator().next();
assertNotNull("The stored retained message must be present after client's session drop", storedPublish);
}
@Test
public void testStoreRetained() throws UnsupportedEncodingException {
StoredMessage msgStored = new StoredMessage("Hello".getBytes(UTF_8), MqttQoS.AT_LEAST_ONCE, "/topic");
msgStored.setClientID(TEST_CLIENT);
messagesStore.storeRetained(asTopic("/topic"), msgStored);
//Verify the message is in the store
StoredMessage msgRetrieved = messagesStore.searchMatching(new IMatchingCondition() {
@Override
public boolean match(Topic key) {
return key.match(new Topic("/topic"));
}
}).iterator().next();
final ByteBuf payload = msgRetrieved.getPayload();
byte[] content = new byte[payload.readableBytes()];
payload.readBytes(content);
assertEquals("Hello", new String(content, UTF_8));
}
@Test
public void givenSubscriptionAlreadyStoredIsOverwrittenByAnotherWithSameTopic() {
ClientSession session1 = sessionsRepository.createNewSession("SESSION_ID_1", false);
// Subscribe on /topic with QOSType.MOST_ONE
Subscription oldSubscription = new Subscription(session1.clientID, new Topic("/topic"), AT_MOST_ONCE);
session1.subscribe(oldSubscription);
// Subscribe on /topic again that overrides the previous subscription.
Subscription overridingSubscription = new Subscription(session1.clientID, new Topic("/topic"), EXACTLY_ONCE);
session1.subscribe(overridingSubscription);
// Verify
final ISubscriptionsStore subscriptionsStore = sessionsStore.subscriptionStore();
List<Subscription> subscriptions = subscriptionsStore.listAllSubscriptions();
assertEquals(1, subscriptions.size());
Subscription sub = subscriptions.get(0);
assertEquals(overridingSubscription.getRequestedQos(), sub.getRequestedQos());
}
}
@@ -25,6 +25,7 @@ import io.moquette.persistence.MemoryStorageService;
import io.moquette.persistence.MemorySessionStore;
import io.moquette.spi.security.IAuthenticator;
import io.moquette.spi.security.IAuthorizatorPolicy;
import io.moquette.broker.Server;
import org.junit.After;
import org.junit.Test;
import java.io.IOException;
@@ -43,7 +44,7 @@ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizat
}
@After
public void tearDown() throws Exception {
public void tearDown() {
m_server.stopServer();
}
@@ -63,15 +64,15 @@ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizat
assertTrue(true);
}
@Test
public void loadStorage() throws Exception {
Properties props = new Properties(IntegrationUtils.prepareTestProperties());
props.setProperty(BrokerConstants.STORAGE_CLASS_NAME, MemoryStorageService.class.getName());
startServer(props);
assertTrue(m_server.getProcessor().getMessagesStore() instanceof MemoryMessagesStore);
assertTrue(m_server.getProcessor().getSessionsStore() instanceof MemorySessionStore);
}
// @Test
// public void loadStorage() throws Exception {
// Properties props = new Properties(IntegrationUtils.prepareTestProperties());
// props.setProperty(BrokerConstants.STORAGE_CLASS_NAME, MemoryStorageService.class.getName());
//
// startServer(props);
// assertTrue(m_server.getProcessor().getMessagesStore() instanceof MemoryMessagesStore);
// assertTrue(m_server.getProcessor().getSessionsStore() instanceof MemorySessionStore);
// }
@Override
public boolean checkValid(String clientID, String username, byte[] password) {
@@ -18,6 +18,7 @@ package io.moquette.server;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.util.concurrent.*;
@@ -89,7 +90,7 @@ public class MessageCollector implements MqttCallback {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
public void messageArrived(String topic, MqttMessage message) {
m_messages.offer(new ReceivedMessage(message, topic));
}
@@ -98,10 +99,11 @@ public class MessageCollector implements MqttCallback {
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// try {
// m_messages.offer(new ReceivedMessage(token.waitMessage(), token.getTopics()[0]));
// } catch (MqttException e) {
// e.printStackTrace();
// }
// try {
// token.waitForCompletion(1_000);
// m_messages.offer(new ReceivedMessage(token.getMessage(), token.getTopics()[0]));
// } catch (MqttException e) {
// e.printStackTrace();
// }
}
}
@@ -18,6 +18,7 @@ package io.moquette.server;
import io.moquette.BrokerConstants;
import io.moquette.server.config.IConfig;
import io.moquette.broker.Server;
import io.moquette.server.config.MemoryConfig;
import io.moquette.spi.impl.security.DBAuthenticator;
import io.moquette.spi.impl.security.DBAuthenticatorTest;
@@ -18,6 +18,7 @@ package io.moquette.server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import io.moquette.broker.Server;
import org.fusesource.mqtt.client.*;
import org.junit.After;
import org.junit.Before;
@@ -97,7 +98,7 @@ public class ServerIntegrationFuseTest {
m_publisher.kill();
// Verify, that the testament is fired
Message msg = m_subscriber.receive(500, TimeUnit.MILLISECONDS);
Message msg = m_subscriber.receive(1, TimeUnit.SECONDS); // wait the flush interval (1 sec)
assertNotNull("We should get notified with 'Will' message", msg);
msg.ack();
assertEquals(willTestamentMsg, new String(msg.getPayload(), UTF_8));
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.Properties;
import io.moquette.BrokerConstants;
import io.moquette.broker.Server;
import io.netty.handler.ssl.OpenSsl;
import io.netty.handler.ssl.SslProvider;
import org.junit.BeforeClass;
@@ -19,6 +19,7 @@ package io.moquette.server;
import io.moquette.BrokerConstants;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import io.moquette.broker.Server;
import io.moquette.spi.impl.security.AcceptAllAuthenticator;
import io.moquette.spi.impl.subscriptions.Topic;
import io.moquette.spi.security.IAuthorizatorPolicy;
@@ -39,7 +40,8 @@ import java.io.File;
import java.io.IOException;
import java.util.Properties;
import static io.moquette.spi.impl.ProtocolProcessorTest.EMPTY_OBSERVERS;
import static io.moquette.broker.ConnectionTestUtils.*;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;
@@ -115,6 +117,7 @@ public class ServerIntegrationPahoCanPublishOnReadBlockedTopicTest {
m_server.stopServer();
}
// TODO move this functional test into unit/integration
@Test
public void shouldNotInternalPublishOnReadBlockedSubscriptionTopic() throws Exception {
LOG.info("*** shouldNotInternalPublishOnReadBlockedSubscriptionTopic ***");
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import org.eclipse.paho.client.mqttv3.*;
@@ -141,6 +142,7 @@ public class ServerIntegrationPahoTest {
subscriberA.disconnect();
MqttMessage messageOnB = cbSubscriberB.waitMessage(1);
assertNotNull("MUST be a received message", messageOnB);
assertEquals("Hello world MQTT!!", new String(messageOnB.getPayload(), UTF_8));
assertEquals(2, messageOnB.getQos());
subscriberB.disconnect();
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import org.eclipse.paho.client.mqttv3.IMqttClient;
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import org.eclipse.paho.client.mqttv3.*;
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import static org.junit.Assert.assertFalse;
import java.io.File;
import java.io.IOException;
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertFalse;
import java.io.File;
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import io.moquette.BrokerConstants;
import io.moquette.server.config.MemoryConfig;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
@@ -16,6 +16,7 @@
package io.moquette.server;
import io.moquette.broker.Server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import io.moquette.testclient.Client;
@@ -97,8 +98,8 @@ public class ServerLowlevelMessagesIntegrationTests {
MqttConnectVariableHeader mqttConnectVariableHeader = new MqttConnectVariableHeader(
MqttVersion.MQTT_3_1.protocolName(), MqttVersion.MQTT_3_1.protocolLevel(), false, false, false, 1, false,
true, keepAlive);
MqttConnectPayload mqttConnectPayload = new MqttConnectPayload(clientID, (String) null, (byte[]) null,
(String) null, (byte[]) null);
MqttConnectPayload mqttConnectPayload = new MqttConnectPayload(clientID, null, null,
null, (byte[]) null);
return new MqttConnectMessage(mqttFixedHeader, mqttConnectVariableHeader, mqttConnectPayload);
}
@@ -16,12 +16,12 @@
package io.moquette.spec.v3_1_1.connection;
import io.moquette.broker.Server;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import io.moquette.BrokerConstants;
import io.moquette.server.Server;
import io.moquette.testclient.RawClient;
import org.junit.After;
import org.junit.Before;
@@ -1,79 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.impl.SessionsRepository;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
import io.moquette.spi.impl.subscriptions.Subscription;
import io.moquette.spi.impl.subscriptions.Topic;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
import static io.netty.handler.codec.mqtt.MqttQoS.EXACTLY_ONCE;
import static org.junit.Assert.assertEquals;
public class ClientSessionTest {
private ISubscriptionsDirectory subscriptionsDirectory;
private SessionsRepository sessionsRepository;
@Before
public void setUp() {
subscriptionsDirectory = new CTrieSubscriptionDirectory();
MemoryStorageService storageService = new MemoryStorageService(null, null);
ISessionsStore sessionsStore = storageService.sessionsStore();
sessionsRepository = new SessionsRepository(sessionsStore, null);
subscriptionsDirectory.init(sessionsRepository);
}
@Test
public void overridingSubscriptionsForTransientSession() {
ClientSession sessionClean = sessionsRepository.createNewSession("SESSION_ID_1", true);
checkOverridingSubcription(sessionClean);
}
@Test
public void overridingSubscriptionsForPersistentSession() {
ClientSession sessionClean = sessionsRepository.createNewSession("SESSION_ID_1", false);
checkOverridingSubcription(sessionClean);
}
private void checkOverridingSubcription(ClientSession sessionClean) {
// Subscribe on /topic with QOSType.MOST_ONE
Subscription oldSubscription = new Subscription(sessionClean.clientID, new Topic("/topic"), AT_MOST_ONCE);
sessionClean.subscribe(oldSubscription);
subscriptionsDirectory.add(oldSubscription);
// Subscribe on /topic again that overrides the previous subscription.
Subscription overridingSubscription = new Subscription(sessionClean.clientID, new Topic("/topic"),
EXACTLY_ONCE);
sessionClean.subscribe(overridingSubscription);
subscriptionsDirectory.add(overridingSubscription);
// Verify
List<Subscription> subscriptions = subscriptionsDirectory.matches(new Topic("/topic"));
assertEquals("Only one subscription must match /topic", 1, subscriptions.size());
Subscription sub = subscriptions.get(0);
assertEquals("Matching subscription MUST have higher QoS",
overridingSubscription.getRequestedQos(), sub.getRequestedQos());
}
}
@@ -1,332 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.IMessagesStore;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.*;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.mqtt.*;
import java.util.*;
import static io.moquette.spi.impl.ProtocolProcessorTest.NO_OBSERVERS_INTERCEPTOR;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED;
import static io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader.from;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
abstract class AbstractProtocolProcessorCommonUtils {
static final String FAKE_CLIENT_ID = "FAKE_123";
static final String FAKE_CLIENT_ID2 = "FAKE_456";
static final String TEST_USER = "fakeuser";
static final String TEST_PWD = "fakepwd";
static final String HELLO_WORLD_MQTT = "Hello world MQTT!!";
EmbeddedChannel m_channel;
ProtocolProcessor m_processor;
IMessagesStore m_messagesStore;
ISessionsStore m_sessionStore;
ISubscriptionsDirectory subscriptions;
MockAuthenticator m_mockAuthenticator;
SessionsRepository sessionsRepository;
protected void initializeProcessorAndSubsystems() {
m_channel = new EmbeddedChannel();
NettyUtils.clientID(m_channel, FAKE_CLIENT_ID);
NettyUtils.cleanSession(m_channel, false);
// sleep to let the messaging batch processor to process the initEvent
MemoryStorageService memStorage = new MemoryStorageService(null, null);
m_messagesStore = memStorage.messagesStore();
m_sessionStore = memStorage.sessionsStore();
// m_messagesStore.initStore();
sessionsRepository = new SessionsRepository(m_sessionStore, null);
Set<String> clientIds = new HashSet<>();
clientIds.add(FAKE_CLIENT_ID);
clientIds.add(FAKE_CLIENT_ID2);
Map<String, String> users = new HashMap<>();
users.put(TEST_USER, TEST_PWD);
m_mockAuthenticator = new MockAuthenticator(clientIds, users);
subscriptions = new CTrieSubscriptionDirectory();
subscriptions.init(sessionsRepository);
m_processor = new ProtocolProcessor();
m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true,
new PermitAllAuthorizatorPolicy(), NO_OBSERVERS_INTERCEPTOR, sessionsRepository, false);
}
void verifyNoPublishIsReceived() {
verifyNoPublishIsReceived(this.m_channel);
}
void verifyNoPublishIsReceived(EmbeddedChannel channel) {
final Object messageReceived = channel.readOutbound();
assertNull("Received an out message from processor while not expected", messageReceived);
}
protected void subscribe(String topic, MqttQoS desiredQos) {
subscribe(this.m_channel, topic, desiredQos);
}
protected void subscribe(EmbeddedChannel channel, String topic, MqttQoS desiredQos) {
MqttSubscribeMessage subscribe = MqttMessageBuilders.subscribe()
.addSubscription(desiredQos, topic)
.messageId(1)
.build();
this.m_processor.processSubscribe(channel, subscribe);
MqttSubAckMessage subAck = channel.readOutbound();
assertEquals(desiredQos.value(), (int) subAck.payload().grantedQoSLevels().get(0));
final String clientId = NettyUtils.clientID(channel);
Subscription expectedSubscription = new Subscription(clientId, new Topic(topic), desiredQos);
verifySubscriptionExists(m_sessionStore, expectedSubscription);
}
protected void subscribeWithFail(EmbeddedChannel channel, String topic, MqttQoS desiredQos) {
MqttSubscribeMessage subscribe = MqttMessageBuilders.subscribe()
.addSubscription(desiredQos, topic)
.messageId(1)
.build();
this.m_processor.processSubscribe(channel, subscribe);
MqttSubAckMessage subAck = channel.readOutbound();
assertEquals(MqttQoS.FAILURE.value(), (int) subAck.payload().grantedQoSLevels().get(0));
}
protected static void verifySubscriptionExists(ISessionsStore sessionsStore, Subscription expectedSubscription) {
final Subscription subscription = sessionsStore.subscriptionStore().reload(expectedSubscription);
assertEquals(expectedSubscription, subscription);
}
// protected MqttSubAckMessage subscribeWithoutVerify(String topic, MqttQoS desiredQos) {
// MqttSubscribeMessage subscribe = MqttMessageBuilders.subscribe()
// .addSubscription(desiredQos, topic)
// .messageId(1)
// .build();
// this.m_processor.processSubscribe(m_channel, subscribe);
// return m_channel.readOutbound();
// }
protected void subscribeAndNotReadResponse(String topic, MqttQoS desiredQos) {
MqttSubscribeMessage subscribe = MqttMessageBuilders.subscribe()
.addSubscription(desiredQos, topic)
.messageId(1)
.build();
this.m_processor.processSubscribe(m_channel, subscribe);
}
protected void unsubscribeAndVerifyAck(String topic) {
final int messageId = 1;
MqttUnsubscribeMessage msg = MqttMessageBuilders.unsubscribe()
.addTopicFilter(topic)
.messageId(messageId)
.build();
m_processor.processUnsubscribe(m_channel, msg);
MqttUnsubAckMessage unsubAckMessageAck = m_channel.readOutbound();
assertEquals("Unsubscribe must be accepted", messageId, unsubAckMessageAck.variableHeader().messageId());
}
protected void internalPublishNotRetainedTo(String topic) {
internalPublishTo(topic, AT_MOST_ONCE, false);
}
protected void internalPublishRetainedTo(String topic) {
internalPublishTo(topic, AT_MOST_ONCE, true);
}
protected void internalPublishTo(String topic, MqttQoS qos, boolean retained) {
MqttPublishMessage publish = MqttMessageBuilders.publish()
.topicName(topic)
.retained(retained)
.qos(qos)
.payload(Unpooled.copiedBuffer(HELLO_WORLD_MQTT.getBytes(UTF_8))).build();
this.m_processor.internalPublish(publish, "INTRPUBL");
}
protected void publishToAs(String clientId, String topic, MqttQoS qos, boolean retained) {
publishToAs(m_channel, clientId, topic, qos, retained);
}
protected void publishToAs(EmbeddedChannel channel, String clientId, String topic, MqttQoS qos, boolean retained) {
NettyUtils.userName(channel, clientId);
MqttPublishMessage publish = MqttMessageBuilders.publish()
.topicName(topic)
.retained(retained)
.qos(qos)
.payload(Unpooled.copiedBuffer(HELLO_WORLD_MQTT.getBytes(UTF_8))).build();
this.m_processor.processPublish(m_channel, publish);
}
protected void publishToAs(String clientId, String topic, MqttQoS qos, int messageId, boolean retained) {
publishToAs(this.m_channel, clientId, topic, qos, messageId, retained);
}
protected void publishToAs(EmbeddedChannel channel, String clientId, String topic, MqttQoS qos, int messageId,
boolean retained) {
publishToAs(channel, clientId, topic, HELLO_WORLD_MQTT, qos, messageId, retained);
}
protected void publishToAs(EmbeddedChannel channel, String clientId, String topic, String payload, MqttQoS qos,
int messageId, boolean retained) {
NettyUtils.userName(channel, clientId);
MqttPublishMessage publish = MqttMessageBuilders.publish()
.topicName(topic)
.retained(retained)
.messageId(messageId)
.qos(qos)
.payload(Unpooled.copiedBuffer(payload.getBytes(UTF_8))).build();
this.m_processor.processPublish(channel, publish);
}
protected void publishQoS2ToAs(EmbeddedChannel channel, String clientId, String topic, int messageId,
boolean retained) {
publishQoS2ToAs(channel, clientId, topic, HELLO_WORLD_MQTT, messageId, retained);
}
protected void publishQoS2ToAs(EmbeddedChannel channel, String clientId, String topic, String payload,
int messageId, boolean retained) {
NettyUtils.userName(channel, clientId);
MqttPublishMessage publish = MqttMessageBuilders.publish()
.topicName(topic)
.retained(retained)
.messageId(messageId)
.qos(MqttQoS.EXACTLY_ONCE)
.payload(Unpooled.copiedBuffer(payload.getBytes(UTF_8))).build();
this.m_processor.processPublish(channel, publish);
verifyPubrecIsReceived(channel, messageId);
MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBREL, false, AT_LEAST_ONCE, false, 0);
MqttMessage pubRel = new MqttMessage(mqttFixedHeader, from(messageId));
this.m_processor.processPubRel(channel, pubRel);
verifyPubCompIsReceived(channel, messageId);
}
private void verifyPubrecIsReceived(EmbeddedChannel channel, int messageId) {
final MqttMessage pubRec = channel.readOutbound();
assertEquals(messageId, Utils.messageId(pubRec));
}
private void verifyPubCompIsReceived(EmbeddedChannel channel, int messageId) {
final MqttMessage pubComp = channel.readOutbound();
assertEquals(messageId, Utils.messageId(pubComp));
}
protected void connect() {
connectAsClient(FAKE_CLIENT_ID);
}
protected void connectAsClient(String clientId) {
connectAsClient(m_channel, clientId);
}
protected void connectAsClient(EmbeddedChannel channel, String clientId) {
MqttConnectMessage connectMessage = MqttMessageBuilders.connect()
.clientId(clientId)
.build();
this.m_processor.processConnect(channel, connectMessage);
MqttConnAckMessage connAck = channel.readOutbound();
assertEquals("Connect must be accepted", CONNECTION_ACCEPTED, connAck.variableHeader().connectReturnCode());
}
protected void connect_v3_1() {
connect_v3_1_asClient(FAKE_CLIENT_ID);
}
protected void connect_v3_1_asClient(String clientID) {
MqttConnectMessage connectMessage = MqttMessageBuilders.connect()
.clientId(clientID)
.cleanSession(true)
.protocolVersion(MqttVersion.MQTT_3_1)
.build();
this.m_processor.processConnect(m_channel, connectMessage);
MqttConnAckMessage connAck = m_channel.readOutbound();
assertEquals("Connect must be accepted", CONNECTION_ACCEPTED, connAck.variableHeader().connectReturnCode());
}
protected void connectNoCleanSession() {
connectNoCleanSession(FAKE_CLIENT_ID);
}
protected void connectNoCleanSession(String clientId) {
MqttConnectMessage connectMessage = MqttMessageBuilders.connect()
.clientId(clientId)
.cleanSession(false)
.build();
this.m_processor.processConnect(m_channel, connectMessage);
MqttConnAckMessage connAck = m_channel.readOutbound();
assertEquals("Connect must be accepted", CONNECTION_ACCEPTED, connAck.variableHeader().connectReturnCode());
}
protected void connectWithCleanSession(String clientId) {
MqttConnectMessage connectMessage = MqttMessageBuilders.connect()
.clientId(clientId)
.cleanSession(true)
.build();
this.m_processor.processConnect(m_channel, connectMessage);
MqttConnAckMessage connAck = m_channel.readOutbound();
assertEquals("Connect must be accepted", CONNECTION_ACCEPTED, connAck.variableHeader().connectReturnCode());
}
protected void disconnect() {
disconnect(this.m_channel);
}
protected void disconnect(EmbeddedChannel channel) {
this.m_processor.processDisconnect(channel);
}
protected void verifyPublishIsReceived() {
verifyPublishIsReceived(m_channel);
}
protected void verifyPublishIsReceived(EmbeddedChannel channel) {
final MqttPublishMessage publishReceived = channel.readOutbound();
String payloadMessage = new String(publishReceived.payload().array(), UTF_8);
assertEquals("Sent and received payload must be identical", HELLO_WORLD_MQTT, payloadMessage);
}
protected void verifyPublishIsReceived(MqttQoS expectedQoS) {
verifyPublishIsReceived(HELLO_WORLD_MQTT, expectedQoS);
}
protected void verifyPublishIsReceived(String expectedPayload, MqttQoS expectedQoS) {
verifyPublishIsReceived(this.m_channel, expectedPayload, expectedQoS);
}
protected void verifyPublishIsReceived(EmbeddedChannel channel, String expectedPayload, MqttQoS expectedQoS) {
final MqttPublishMessage publishReceived = channel.readOutbound();
String payloadMessage = new String(publishReceived.payload().array(), UTF_8);
assertEquals("Sent and received payload must be identical", expectedPayload, payloadMessage);
assertEquals("Expected QoS don't match", expectedQoS, publishReceived.fixedHeader().qosLevel());
}
}
@@ -1,307 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.moquette.broker.PostOfficePublishTest;
import io.moquette.interception.InterceptHandler;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.IMessagesStore;
import io.moquette.spi.IMessagesStore.StoredMessage;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
import io.moquette.spi.impl.subscriptions.Subscription;
import io.moquette.spi.impl.subscriptions.Topic;
import io.moquette.spi.security.IAuthorizatorPolicy;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.mqtt.*;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static io.moquette.spi.impl.NettyChannelAssertions.assertConnAckAccepted;
import static io.moquette.spi.impl.ProtocolProcessor.lowerQosToTheSubscriptionDesired;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
import static io.netty.handler.codec.mqtt.MqttQoS.EXACTLY_ONCE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class ProtocolProcessorTest extends AbstractProtocolProcessorCommonUtils {
static final String FAKE_CLIENT_ID = "FAKE_123";
static final String FAKE_CLIENT_ID2 = "FAKE_456";
static final String PUBLISHER_ID = "Publisher";
private static final String SUBSCRIBER_ID = "Subscriber";
static final String NEWS_TOPIC = "/news";
static final String BAD_FORMATTED_TOPIC = "#MQTTClient";
static final String TEST_USER = "fakeuser";
static final String TEST_PWD = "fakepwd";
static final String EVIL_TEST_USER = "eviluser";
static final String EVIL_TEST_PWD = "unsecret";
public static final List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList();
public static final BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS);
@Before
public void setUp() {
initializeProcessorAndSubsystems();
}
//same test moved into PostOfficePublishTest
// @Test
// public void testPublishToItself() {
// final Subscription subscription = new Subscription(FAKE_CLIENT_ID, new Topic(NEWS_TOPIC), AT_MOST_ONCE);
//
// // subscriptions.matches(topic) redefine the method to return true
// ISubscriptionsDirectory subs = new CTrieSubscriptionDirectory() {
//
// @Override
// public List<Subscription> matches(Topic topic) {
// if (topic.toString().equals(NEWS_TOPIC)) {
// return Collections.singletonList(subscription);
// } else {
// throw new IllegalArgumentException("Expected " + NEWS_TOPIC + " buf found " + topic);
// }
// }
// };
//
// // simulate a connect that register a clientID to an IoSession
// MemoryStorageService storageService = new MemoryStorageService(null, null);
// SessionsRepository sessionsRepository = new SessionsRepository(storageService.sessionsStore(), null);
// subs.init(sessionsRepository);
// m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
// NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
//
// connect_v3_1();
//
// // Exercise
// publishToAs("FakeCLI", NEWS_TOPIC, AT_MOST_ONCE, false);
//
// // Verify
// verifyPublishIsReceived();
// }
//same test moved into PostOfficePublishTest
// @Test
// public void testPublishToMultipleSubscribers() {
// final Subscription subscription = new Subscription(FAKE_CLIENT_ID, new Topic(NEWS_TOPIC), AT_MOST_ONCE);
// final Subscription subscriptionClient2 = new Subscription(
// FAKE_CLIENT_ID2,
// new Topic(NEWS_TOPIC),
// AT_MOST_ONCE);
//
// // subscriptions.matches(topic) redefine the method to return true
// ISubscriptionsDirectory subs = new CTrieSubscriptionDirectory() {
//
// @Override
// public List<Subscription> matches(Topic topic) {
// if (topic.toString().equals(NEWS_TOPIC)) {
// return Arrays.asList(subscription, subscriptionClient2);
// } else {
// throw new IllegalArgumentException("Expected " + NEWS_TOPIC + " buf found " + topic);
// }
// }
// };
//
// // simulate a connect that register a clientID to an IoSession
// MemoryStorageService storageService = new MemoryStorageService(null, null);
// SessionsRepository sessionsRepository = new SessionsRepository(storageService.sessionsStore(), null);
// subs.init(sessionsRepository);
// m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
// NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
//
// EmbeddedChannel firstReceiverChannel = new EmbeddedChannel();
// MqttConnectMessage connectMessage = MqttMessageBuilders.connect().protocolVersion(MqttVersion.MQTT_3_1)
// .clientId(FAKE_CLIENT_ID).cleanSession(true).build();
// m_processor.processConnect(firstReceiverChannel, connectMessage);
// assertConnAckAccepted(firstReceiverChannel);
//
// // connect the second fake subscriber
// EmbeddedChannel secondReceiverChannel = new EmbeddedChannel();
// MqttConnectMessage connectMessage2 = MqttMessageBuilders.connect().protocolVersion(MqttVersion.MQTT_3_1)
// .clientId(FAKE_CLIENT_ID2).cleanSession(true).build();
// m_processor.processConnect(secondReceiverChannel, connectMessage2);
// assertConnAckAccepted(secondReceiverChannel);
//
// // Exercise
// MqttPublishMessage msg = MqttMessageBuilders.publish().topicName(NEWS_TOPIC).qos(AT_MOST_ONCE)
// .retained(false).payload(Unpooled.copiedBuffer("Hello".getBytes(UTF_8))).build();
// NettyUtils.userName(m_channel, "FakeCLI");
// m_processor.processPublish(m_channel, msg);
//
// // Verify
// firstReceiverChannel.flush();
// MqttPublishMessage pub2FirstSubscriber = firstReceiverChannel.readOutbound();
// assertNotNull(pub2FirstSubscriber);
// String firstMessageContent = DebugUtils.payload2Str(pub2FirstSubscriber.payload());
// assertEquals("Hello", firstMessageContent);
//
// secondReceiverChannel.flush();
// MqttPublishMessage pub2SecondSubscriber = secondReceiverChannel.readOutbound();
// assertNotNull(pub2SecondSubscriber);
// String secondMessageContent = DebugUtils.payload2Str(pub2SecondSubscriber.payload());
// assertEquals("Hello", secondMessageContent);
// }
//
// //TODO move this test on PostOfficeSubscribeTest
// @Test
// public void testPublishOfRetainedMessage_afterNewSubscription() throws Exception {
// // simulate a connect that register a clientID to an IoSession
// final Subscription subscription =
// new Subscription(PUBLISHER_ID, new Topic(NEWS_TOPIC), AT_MOST_ONCE);
//
// // subscriptions.matches(topic) redefine the method to return true
// ISubscriptionsDirectory subs = new CTrieSubscriptionDirectory() {
//
// @Override
// public List<Subscription> matches(Topic topic) {
// if (topic.toString().equals(NEWS_TOPIC)) {
// return Collections.singletonList(subscription);
// } else {
// throw new IllegalArgumentException("Expected " + NEWS_TOPIC + " buf found " + topic);
// }
// }
// };
// MemoryStorageService storageService = new MemoryStorageService(null, null);
// SessionsRepository sessionsRepository = new SessionsRepository(storageService.sessionsStore(), null);
// subs.init(sessionsRepository);
//
// // simulate a connect that register a clientID to an IoSession
// m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
// NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
// connect_v3_1_asClient(PUBLISHER_ID);
// publishToAs(PUBLISHER_ID, NEWS_TOPIC, AT_MOST_ONCE, true);
// NettyUtils.cleanSession(m_channel, false);
//
// // Exercise
// subscribeAndNotReadResponse("#", AT_MOST_ONCE);
//
// // Verify
// verifyPublishIsReceived();
// }
@Test
public void testRepublishAndConsumePersistedMessages_onReconnect() {
ISubscriptionsDirectory subs = mock(ISubscriptionsDirectory.class);
List<Subscription> emptySubs = Collections.emptyList();
when(subs.matches(any(Topic.class))).thenReturn(emptySubs);
StoredMessage retainedMessage = new StoredMessage("Hello".getBytes(UTF_8), EXACTLY_ONCE, "/topic");
retainedMessage.setRetained(true);
retainedMessage.setClientID(PUBLISHER_ID);
m_messagesStore.storeRetained(new Topic("/topic"), retainedMessage);
m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
connect_v3_1_asClient(PUBLISHER_ID);
// Verify no messages are still stored
assertTrue(this.sessionsRepository.sessionForClient(PUBLISHER_ID).isEmptyQueue());
}
// Moved to PostOfficePublishTest
// @Test
// public void publishNoPublishToInactiveSession() {
// // create an inactive session for Subscriber
// ISubscriptionsDirectory mockedSubscriptions = mock(ISubscriptionsDirectory.class);
// Subscription inactiveSub = new Subscription("Subscriber", new Topic("/topic"), MqttQoS.AT_LEAST_ONCE);
// List<Subscription> inactiveSubscriptions = Collections.singletonList(inactiveSub);
// when(mockedSubscriptions.matches(eq(new Topic("/topic")))).thenReturn(inactiveSubscriptions);
// m_processor = new ProtocolProcessor();
// m_processor.init(mockedSubscriptions, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
// NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
//
// m_processor.sessionsRepository.createNewSession("Subscriber", false);
//
// // Exercise
// connectAsClient("Publisher");
// publishToAs("Publisher", "/topic", AT_MOST_ONCE, true);
//
// verifyNoPublishIsReceived();
// }
//
// /**
// * Verify that receiving a publish with retained message and with Q0S = 0 clean the existing
// * retained messages for that topic.
// */
// @Test
// public void testCleanRetainedStoreAfterAQoS0AndRetainedTrue() {
// // force a connect
// connect_v3_1_asClient("Publisher");
//
// // prepare and existing retained store
// publishToAs("Publisher", NEWS_TOPIC, AT_LEAST_ONCE, 100, true);
//
// Collection<IMessagesStore.StoredMessage> messages = m_messagesStore
// .searchMatching(key -> key.match(new Topic(NEWS_TOPIC)));
// assertFalse(messages.isEmpty());
//
// // Exercise
// // send a message that clean the previous retained publish
// publishToAs("Publisher", NEWS_TOPIC, AT_MOST_ONCE, true);
//
// // Verify
// messages = m_messagesStore.searchMatching(key -> key.match(new Topic(NEWS_TOPIC)));
// assertTrue(messages.isEmpty());
// }
//
// @Test
// public void testLowerTheQosToTheRequestedBySubscription() {
// Subscription subQos1 = new Subscription("Sub A", new Topic("a/b"), MqttQoS.AT_LEAST_ONCE);
// assertEquals(MqttQoS.AT_LEAST_ONCE, lowerQosToTheSubscriptionDesired(subQos1, EXACTLY_ONCE));
//
// Subscription subQos2 = new Subscription("Sub B", new Topic("a/+"), EXACTLY_ONCE);
// assertEquals(EXACTLY_ONCE, lowerQosToTheSubscriptionDesired(subQos2, EXACTLY_ONCE));
// }
//
// @Test
// public void testSubscribeReceivePublishedMessageAtSubscriberQoSAndNotPublisherQoS() {
// ISubscriptionsDirectory subs = new CTrieSubscriptionDirectory();
// MemoryStorageService storageService = new MemoryStorageService(null, null);
// SessionsRepository sessionsRepository = new SessionsRepository(storageService.sessionsStore(), null);
// subs.init(sessionsRepository);
//
// // simulate a connect that register a clientID to an IoSession
// m_processor.init(subs, m_messagesStore, m_sessionStore, null, true, new PermitAllAuthorizatorPolicy(),
// NO_OBSERVERS_INTERCEPTOR, this.sessionsRepository, false);
// connect_v3_1_asClient(PUBLISHER_ID);
// publishQoS2ToAs(this.m_channel, PUBLISHER_ID, NEWS_TOPIC, 1, true);
// disconnect();
//
// // connect from the subscriber
// EmbeddedChannel subscriberChannel = new EmbeddedChannel();
// NettyUtils.clientID(subscriberChannel, SUBSCRIBER_ID);
// NettyUtils.cleanSession(subscriberChannel, false);
// connectAsClient(subscriberChannel, SUBSCRIBER_ID);
//
// // subscribe to the topic news with granted QoS0
// subscribe(subscriberChannel, NEWS_TOPIC, MqttQoS.AT_MOST_ONCE);
//
// // Verify the retained message arrives with QoS0 instead of QoS2
// verifyPublishIsReceived(subscriberChannel, HELLO_WORLD_MQTT, MqttQoS.AT_MOST_ONCE);
// }
}
@@ -1,101 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.server.netty.NettyUtils;
import io.moquette.spi.IMessagesStore;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.security.PermitAllAuthorizatorPolicy;
import io.moquette.spi.impl.subscriptions.CTrieSubscriptionDirectory;
import io.moquette.spi.impl.subscriptions.ISubscriptionsDirectory;
import io.moquette.spi.impl.subscriptions.Subscription;
import io.moquette.spi.impl.subscriptions.Topic;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.mqtt.*;
import org.junit.Before;
import org.junit.Test;
import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsConnAck;
import static io.moquette.spi.impl.NettyChannelAssertions.assertEqualsSubAck;
import static io.moquette.spi.impl.ProtocolProcessorTest.*;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonMap;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ProtocolProcessor_CONNECT_Test {
private EmbeddedChannel session;
private ProtocolProcessor processor;
private ISessionsStore sessionStore;
@Before
public void setUp() {
session = new EmbeddedChannel();
MemoryStorageService memStorage = new MemoryStorageService(null, null);
IMessagesStore m_messagesStore = memStorage.messagesStore();
sessionStore = memStorage.sessionsStore();
MockAuthenticator mockAuthenticator = new MockAuthenticator(singleton(FAKE_CLIENT_ID), singletonMap(TEST_USER, TEST_PWD));
ISubscriptionsDirectory subscriptions = new CTrieSubscriptionDirectory();
SessionsRepository sessionsRepository = new SessionsRepository(sessionStore, null);
subscriptions.init(sessionsRepository);
processor = new ProtocolProcessor();
processor.init(subscriptions, m_messagesStore, sessionStore, mockAuthenticator, true,
new PermitAllAuthorizatorPolicy(), NO_OBSERVERS_INTERCEPTOR,
new SessionsRepository(this.sessionStore, null), false);
}
@Test
public void testMultipleReconnection() {
// connect with clean a false and subscribe to a topic
MqttConnectMessage msg = MqttMessageBuilders.connect().clientId(FAKE_CLIENT_ID)
.protocolVersion(MqttVersion.MQTT_3_1_1).build();
processor.processConnect(session, msg);
assertEqualsConnAck(CONNECTION_ACCEPTED, session.readOutbound());
assertTrue("Connection is accepted and therefore should remain open.", session.isOpen());
// subscribe
MqttSubscribeMessage subscribeMsg = MqttMessageBuilders.subscribe()
.addSubscription(MqttQoS.AT_MOST_ONCE, ProtocolProcessorTest.NEWS_TOPIC).messageId(10).build();
NettyUtils.clientID(session, FAKE_CLIENT_ID);
NettyUtils.cleanSession(session, false);
processor.processSubscribe(session, subscribeMsg);
final Topic newTopic = new Topic(ProtocolProcessorTest.NEWS_TOPIC);
Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, newTopic, MqttQoS.AT_MOST_ONCE);
verifySubscriptionExists(sessionStore, expectedSubscription);
assertEqualsSubAck(session.readOutbound());
// disconnect
processor.processDisconnect(session);
assertFalse(session.isOpen());
// reconnect clean session a false
session = new EmbeddedChannel();
processor.processConnect(session, msg);
assertEqualsConnAck(CONNECTION_ACCEPTED, session.readOutbound());
assertTrue("Connection is accepted and therefore should remain open.", session.isOpen());
// verify that the first subscription is still preserved
verifySubscriptionExists(sessionStore, expectedSubscription);
}
}
@@ -1,191 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.moquette.server.netty.NettyUtils;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.junit.Before;
import org.junit.Test;
import static io.netty.handler.codec.mqtt.MqttQoS.*;
import static org.junit.Assert.assertEquals;
public class ProtocolProcessor_InternalPublish_Test extends AbstractProtocolProcessorCommonUtils {
@Before
public void setUp() {
initializeProcessorAndSubsystems();
connect();
}
@Test
public void testClientSubscribeAfterNotRetainedQoS0IsSent() {
// Exercise
final String topic = "/topic";
internalPublishNotRetainedTo(topic);
subscribe(topic, AT_MOST_ONCE);
// Verify
verifyNoPublishIsReceived();
}
@Test
public void testClientSubscribeAfterRetainedQoS0IsSent() {
// Exercise
final String topic = "/topic";
internalPublishRetainedTo(topic);
subscribe(topic, AT_MOST_ONCE);
// Verify
verifyNoPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeNotRetainedQoS0IsSent() {
subscribe("/topic", AT_MOST_ONCE);
// Exercise
internalPublishNotRetainedTo("/topic");
// Verify
//verifyMessageIsReceivedSuccessfully();
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeRetainedQoS0IsSent() {
subscribe("/topic", AT_MOST_ONCE);
// Exercise
internalPublishRetainedTo("/topic");
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeNotRetainedQoS1IsSent() {
subscribe("/topic", AT_LEAST_ONCE);
// Exercise
internalPublishTo("/topic", AT_LEAST_ONCE, false);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeAfterNotRetainedQoS1IsSent() {
// Exercise
internalPublishTo("/topic", AT_LEAST_ONCE, false);
subscribe("/topic", AT_LEAST_ONCE);
// Verify
verifyNoPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeRetainedQoS1IsSent() {
subscribe("/topic", AT_LEAST_ONCE);
// Exercise
internalPublishTo("/topic", AT_LEAST_ONCE, true);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeAfterRetainedQoS1IsSent() {
// Exercise
internalPublishTo("/topic", AT_LEAST_ONCE, true);
subscribe("/topic", AT_LEAST_ONCE);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeNotRetainedQoS2IsSent() {
subscribe("/topic", EXACTLY_ONCE);
// Exercise
internalPublishTo("/topic", EXACTLY_ONCE, false);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeAfterNotRetainedQoS2IsSent() {
// Exercise
internalPublishTo("/topic", EXACTLY_ONCE, false);
subscribe("/topic", EXACTLY_ONCE);
// Verify
verifyNoPublishIsReceived();
}
@Test
public void testClientSubscribeBeforeRetainedQoS2IsSent() {
subscribe("/topic", EXACTLY_ONCE);
// Exercise
internalPublishTo("/topic", EXACTLY_ONCE, true);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeAfterRetainedQoS2IsSent() {
// Exercise
internalPublishTo("/topic", EXACTLY_ONCE, true);
subscribe("/topic", EXACTLY_ONCE);
// Verify
verifyPublishIsReceived();
}
@Test
public void testClientSubscribeAfterDisconnected() throws InterruptedException {
subscribe("foo", AT_MOST_ONCE);
disconnect();
internalPublishTo("foo", AT_MOST_ONCE, false);
verifyNoPublishIsReceived();
}
@Test
public void testClientSubscribeWithoutCleanSession() throws Exception {
subscribe("foo", AT_MOST_ONCE);
disconnect();
assertEquals(1, m_sessionStore.subscriptionStore().listAllSubscriptions().size());
m_channel = new EmbeddedChannel();
NettyUtils.clientID(m_channel, FAKE_CLIENT_ID);
connectNoCleanSession();
assertEquals(1, m_sessionStore.subscriptionStore().listAllSubscriptions().size());
internalPublishTo("foo", MqttQoS.AT_MOST_ONCE, false);
verifyPublishIsReceived();
}
}
@@ -1,363 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.spi.impl;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static io.netty.handler.codec.mqtt.MqttQoS.*;
import static org.junit.Assert.assertFalse;
public class ProtocolProcessor_VariousUseCases_Test extends AbstractProtocolProcessorCommonUtils {
@Before
public void setUp() {
initializeProcessorAndSubsystems();
}
// @Test
// public void testCleanSession_maintainClientSubscriptions() {
// connectAsClient(this.m_channel, "TestClient");
// subscribe("/topic", AT_MOST_ONCE);
// disconnect();
//
// // reconnect and publish
// EmbeddedChannel anotherChannel = new EmbeddedChannel();
// connectAsClient(anotherChannel, "TestClient");
//
// publishToAs(anotherChannel, "TestClient", "/topic", AT_MOST_ONCE, false);
//
// verifyPublishIsReceived(anotherChannel);
// }
//
// @Ignore("At the end it's equal to testCleanSession_maintainClientSubscriptions")
// @Test
// public void testCleanSession_maintainClientSubscriptions_againstClientDestruction() {
// connectAsClient("TestClient");
// subscribe("/topic", AT_MOST_ONCE);
// disconnect();
//
// this.m_channel = new EmbeddedChannel();
// // reconnect and publish
// connectAsClient("TestClient");
//
// publishToAs("TestClient", "/topic", AT_MOST_ONCE, false);
//
// verifyPublishIsReceived();
// }
// /**
// * Check that after a client has connected with clean session false, subscribed to some topic
// * and exited, if it reconnects with clean session true, the broker correctly cleanup every
// * previous subscription
// */
// @Test
// public void testCleanSession_correctlyClientSubscriptions() {
// connectAsClient("TestClient");
// subscribe("/topic", AT_MOST_ONCE);
// disconnect();
//
// this.m_channel = new EmbeddedChannel();
// // reconnect and publish
// connectWithCleanSession("TestClient");
//
// publishToAs("TestClient", "/topic", AT_MOST_ONCE, false);
//
// verifyNoPublishIsReceived();
// }
// Duplicated, just verify retain works correctly
// @Test
// public void testRetain_maintainMessage_againstClientDestruction() {
// connect();
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_LEAST_ONCE, 66, true);
// disconnect();
//
// // reconnect and publish
// this.m_channel = new EmbeddedChannel();
// connect();
// subscribe("/topic", AT_MOST_ONCE);
//
// verifyPublishIsReceived();
// }
// @Test
// public void testUnsubscribe_do_not_notify_anymore_same_session() {
// connect();
// subscribe("/topic", AT_MOST_ONCE);
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, false);
// verifyPublishIsReceived();
//
// unsubscribeAndVerifyAck("/topic");
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, false);
// verifyNoPublishIsReceived();
// }
// @Test
// public void testUnsubscribe_do_not_notify_anymore_new_session() {
// connect();
// subscribe("/topic", AT_MOST_ONCE);
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, false);
// verifyPublishIsReceived();
//
// unsubscribeAndVerifyAck("/topic");
// disconnect();
//
// this.m_channel = new EmbeddedChannel();
// connect();
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, false);
// verifyNoPublishIsReceived();
// }
// Moved to PostOfficePublishTest
// @Test
// public void testPublishWithQoS1() {
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_LEAST_ONCE, 66, false);
// disconnect();
//
// verifyPublishIsReceived(AT_LEAST_ONCE);
// }
// Moved to PostOfficePublishTest.forwardQoS1PublishesWhenNotCleanSessionReconnects
// @Test
// public void testPublishWithQoS1_notCleanSession() {
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
// disconnect();
//
// // publish a QoS 1 message another client publish a message on the topic
// publishFromAnotherClient("/topic", AT_LEAST_ONCE);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// verifyPublishIsReceived();
// }
// private void publishFromAnotherClient(String topic, MqttQoS qos) {
// EmbeddedChannel anotherChannel = new EmbeddedChannel();
// connectAsClient(anotherChannel, "AnotherClient");
// publishToAs(anotherChannel, "AnotherClient", topic, qos, 67, false);
// disconnect(anotherChannel);
// }
// private void publishFromAnotherClient(String topic, String payload, MqttQoS qos) {
// EmbeddedChannel anotherChannel = new EmbeddedChannel();
// connectAsClient(anotherChannel, "AnotherClient");
// publishToAs(anotherChannel, "AnotherClient", topic, payload, qos, 68, false);
// disconnect(anotherChannel);
// }
// private void publishQoS2FromAnotherClient(String topic) {
// EmbeddedChannel anotherChannel = new EmbeddedChannel();
// connectAsClient(anotherChannel, "AnotherClient");
// publishQoS2ToAs(anotherChannel, "AnotherClient", topic, 67, false);
// disconnect(anotherChannel);
// }
// @Test
// public void checkReceivePublishedMessage_after_a_reconnect_with_notCleanSession() {
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
// disconnect();
//
// this.m_channel = new EmbeddedChannel();
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
//
// // publish a QoS 1 message another client publish a message on the topic
// publishFromAnotherClient("/topic", AT_LEAST_ONCE);
//
// // Verify that after a reconnection the client receive the message
// verifyPublishIsReceived();
// }
// @Test
// public void testPublishWithQoS2() {
// connect();
// subscribe("/topic", EXACTLY_ONCE);
// disconnect();
//
// publishQoS2FromAnotherClient("/topic");
//
// this.m_channel = new EmbeddedChannel();
// connect();
//
// verifyPublishIsReceived(EXACTLY_ONCE);
// }
//
// @Test
// public void avoidMultipleNotificationsAfterMultipleReconnection_cleanSessionFalseQoS1() {
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
// disconnect();
//
// publishFromAnotherClient("/topic", "Hello MQTT 1", AT_LEAST_ONCE);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// verifyPublishIsReceived("Hello MQTT 1", AT_LEAST_ONCE);
// disconnect();
//
// // publish other message
// publishFromAnotherClient("/topic", "Hello MQTT 2", AT_LEAST_ONCE);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// verifyPublishIsReceived("Hello MQTT 2", AT_LEAST_ONCE);
// }
// @Test
// public void testConnectSubPub_cycle_getTimeout_on_second_disconnect_issue142() {
// connect();
// subscribe("/topic", AT_MOST_ONCE);
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, true);
// disconnect();
//
// // second loop
// this.m_channel = new EmbeddedChannel();
// connect();
// subscribe("/topic", AT_MOST_ONCE);
// publishToAs(FAKE_CLIENT_ID, "/topic", AT_MOST_ONCE, true);
// disconnect();
//
// assertFalse("after a disconnect the client should be disconnected", this.m_channel.isOpen());
// }
//
// @Test
// public void checkReplayofStoredPublishResumeAfter_a_disconnect_cleanSessionFalseQoS1() {
// EmbeddedChannel publisher = new EmbeddedChannel();
// connectAsClient(publisher, "Publisher");
//
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
//
// publishToAs(publisher, "Publisher", "/topic", "Hello world MQTT!!-1", AT_LEAST_ONCE, 99, false);
// verifyPublishIsReceived("Hello world MQTT!!-1", AT_LEAST_ONCE);
// disconnect();
//
// publishToAs(publisher, "Publisher", "/topic", "Hello world MQTT!!-2", AT_LEAST_ONCE, 100, false);
// publishToAs(publisher, "Publisher", "/topic", "Hello world MQTT!!-3", AT_LEAST_ONCE, 101, false);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// verifyPublishIsReceived("Hello world MQTT!!-2", AT_LEAST_ONCE);
// verifyPublishIsReceived("Hello world MQTT!!-3", AT_LEAST_ONCE);
// }
//
// @Test
// public void checkReplayStoredPublish_forNoCleanSession_qos1() {
// EmbeddedChannel publisher = new EmbeddedChannel();
// connectAsClient(publisher, "Publisher");
//
// connect();
// subscribe("/topic", AT_LEAST_ONCE);
// disconnect();
//
// publishToAs(publisher, "Publisher", "/topic", "Hello world MQTT!!-1", AT_LEAST_ONCE, 99, false);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// subscribeAndNotReadResponse("/topic", AT_LEAST_ONCE);
// verifyPublishIsReceived("Hello world MQTT!!-1", AT_LEAST_ONCE);
// }
//
// /**
// * subscriber connect and subscribe on "topic" subscriber disconnects publisher connects and
// * send two message "hello1" "hello2" to "topic" subscriber connects again and receive "hello1"
// * "hello2"
// */
// @Test
// public void checkQoS2SubscriberDisconnectReceivePersistedPublishes() {
// connect();
// subscribe("topic", EXACTLY_ONCE);
// disconnect();
//
// EmbeddedChannel publisher = new EmbeddedChannel();
// connectAsClient(publisher, "Publisher");
// publishQoS2ToAs(publisher, "Publisher", "topic", "Hello1", 101, true);
// publishQoS2ToAs(publisher, "Publisher", "topic", "Hello2", 102, true);
// disconnect(publisher);
//
// this.m_channel = new EmbeddedChannel();
// connect();
// verifyPublishIsReceived("Hello1", EXACTLY_ONCE);
// verifyPublishIsReceived("Hello2", EXACTLY_ONCE);
// }
// /**
// * subscriber connect and subscribe on "a/b" QoS 1 and "a/+" QoS 2 publisher connects and send a
// * message "hello" on "a/b" subscriber must receive only a single message not twice
// */
// @Test
// public void checkSinglePublishOnOverlappingSubscriptions() {
// EmbeddedChannel publisher = new EmbeddedChannel();
// connectAsClient(publisher, "Publisher");
//
// connect();
// subscribe("a/+", EXACTLY_ONCE);
// subscribe("a/b", AT_LEAST_ONCE);
//
// // force the publisher to send
// publishToAs(publisher, "Publisher", "a/b", "Hello world MQTT!!", AT_LEAST_ONCE, 60, false);
//
// verifyPublishIsReceived("Hello world MQTT!!", AT_LEAST_ONCE);
// // try to listen a second publish
// verifyNoPublishIsReceived();
// }
// @Test
// public void testForceClientDisconnection_issue116() {
// EmbeddedChannel clientXA = new EmbeddedChannel();
// connectAsClient(clientXA, "subscriber");
// subscribe(clientXA, "topic", AT_MOST_ONCE);
//
// EmbeddedChannel clientXB = new EmbeddedChannel();
// connectAsClient(clientXB, "publisher");
// publishQoS2ToAs(clientXB, "publisher", "topic", "Hello", 20, false);
//
// EmbeddedChannel clientYA = new EmbeddedChannel();
// connectAsClient(clientYA, "subscriber");
// subscribe(clientYA, "topic", AT_MOST_ONCE);
//
// EmbeddedChannel clientYB = new EmbeddedChannel();
// connectAsClient(clientYB, "publisher");
// publishQoS2ToAs(clientYB, "publisher", "topic", "Hello 2", 20, true);
//
// assertFalse("First 'subscriber' channel MUST be closed by the broker", clientXA.isOpen());
// verifyPublishIsReceived(clientYA, "Hello 2", AT_MOST_ONCE);
// }
// @Test
// public void testPublishToEmptyTopic() {
// EmbeddedChannel subscriber = new EmbeddedChannel();
// connectAsClient(subscriber, "Subscriber");
//
// subscribe(subscriber, "#", AT_LEAST_ONCE);
//
// // Exercise
// connect();
// publishToAs(FAKE_CLIENT_ID, "", AT_LEAST_ONCE, 1, false);
//
// // Verify
// verifyNoPublishIsReceived(subscriber);
// assertFalse("On empty topic subscription the channel MUST be closed", m_channel.isOpen());
// }
}
@@ -15,11 +15,11 @@
*/
package io.moquette.spi.impl.subscriptions;
import io.moquette.broker.ISubscriptionsRepository;
import io.moquette.broker.MemorySubscriptionsRepository;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ClientSession;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.ISubscriptionsStore;
import io.moquette.spi.impl.SessionsRepository;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.junit.Before;
import org.junit.Test;
@@ -36,17 +36,13 @@ import static org.junit.Assert.assertTrue;
public class CTrieSubscriptionDirectoryMatchingTest {
private CTrieSubscriptionDirectory sut;
private ISubscriptionsStore subscriptionsStore;
private SessionsRepository sessionsRepository;
private ISubscriptionsRepository sessionsRepository;
@Before
public void setUp() {
sut = new CTrieSubscriptionDirectory();
MemoryStorageService storageService = new MemoryStorageService(null, null);
ISessionsStore sessionsStore = storageService.sessionsStore();
this.subscriptionsStore = sessionsStore.subscriptionStore();
this.sessionsRepository = new SessionsRepository(sessionsStore, null);
this.sessionsRepository = new MemorySubscriptionsRepository();
sut.init(this.sessionsRepository);
}
@@ -178,9 +174,7 @@ public class CTrieSubscriptionDirectoryMatchingTest {
private void assertMatch(String s, String t) {
sut = new CTrieSubscriptionDirectory();
MemoryStorageService memStore = new MemoryStorageService(null, null);
ISessionsStore aSessionsStore = memStore.sessionsStore();
SessionsRepository sessionsRepository = new SessionsRepository(aSessionsStore, null);
ISubscriptionsRepository sessionsRepository = new MemorySubscriptionsRepository();
sut.init(sessionsRepository);
Subscription sub = clientSubOnTopic("AnySensor1", s);
@@ -191,9 +185,7 @@ public class CTrieSubscriptionDirectoryMatchingTest {
private void assertNotMatch(String subscription, String topic) {
sut = new CTrieSubscriptionDirectory();
MemoryStorageService memStore = new MemoryStorageService(null, null);
ISessionsStore aSessionsStore = memStore.sessionsStore();
SessionsRepository sessionsRepository = new SessionsRepository(aSessionsStore, null);
ISubscriptionsRepository sessionsRepository = new MemorySubscriptionsRepository();
sut.init(sessionsRepository);
Subscription sub = clientSubOnTopic("AnySensor1", subscription);
@@ -205,18 +197,15 @@ public class CTrieSubscriptionDirectoryMatchingTest {
@Test
public void testOverlappingSubscriptions() {
Subscription genericSub = new Subscription("Sensor1", asTopic("a/+"), MqttQoS.AT_MOST_ONCE);
this.subscriptionsStore.addNewSubscription(genericSub);
final ClientSession sensorSession = this.sessionsRepository.createNewSession("Sensor1", false);
sensorSession.subscribe(genericSub);
this.sessionsRepository.addNewSubscription(genericSub);
sut.add(genericSub);
Subscription specificSub = new Subscription("Sensor1", asTopic("a/b"), MqttQoS.AT_MOST_ONCE);
sensorSession.subscribe(specificSub);
this.subscriptionsStore.addNewSubscription(specificSub);
this.sessionsRepository.addNewSubscription(specificSub);
sut.add(specificSub);
//Exercise
final Set<Subscription> matchingForSpecific = sut.match(asTopic("a/b"));
final Set<Subscription> matchingForSpecific = sut.matchQosSharpening(asTopic("a/b"));
// Verify
assertThat(matchingForSpecific.size()).isEqualTo(1);
@@ -256,21 +245,16 @@ public class CTrieSubscriptionDirectoryMatchingTest {
*/
@Test
public void duplicatedSubscriptionsWithDifferentQos() {
ClientSession session2 = this.sessionsRepository.createNewSession("client2", true);
Subscription client2Sub = new Subscription("client2", asTopic("client/test/b"), MqttQoS.AT_MOST_ONCE);
session2.subscribe(client2Sub);
this.sut.add(client2Sub);
ClientSession session1 = this.sessionsRepository.createNewSession("client1", true);
Subscription client1SubQoS0 = new Subscription("client1", asTopic("client/test/b"), MqttQoS.AT_MOST_ONCE);
session1.subscribe(client1SubQoS0);
this.sut.add(client1SubQoS0);
Subscription client1SubQoS2 = new Subscription("client1", asTopic("client/test/b"), MqttQoS.EXACTLY_ONCE);
session1.subscribe(client1SubQoS2);
this.sut.add(client1SubQoS2);
// Verify
Set<Subscription> subscriptions = this.sut.match(asTopic("client/test/b"));
Set<Subscription> subscriptions = this.sut.matchQosSharpening(asTopic("client/test/b"));
assertThat(subscriptions).contains(client1SubQoS2);
assertThat(subscriptions).contains(client2Sub);
@@ -14,9 +14,10 @@
* You may elect to redistribute this code under either of these licenses.
*/package io.moquette.spi.impl.subscriptions;
import io.moquette.broker.ISubscriptionsRepository;
import io.moquette.broker.MemorySubscriptionsRepository;
import io.moquette.persistence.MemoryStorageService;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.impl.SessionsRepository;
import org.junit.Before;
import org.junit.Test;
@@ -35,9 +36,7 @@ public class CTrieSubscriptionDirectoryTest {
@Before
public void setUp() {
sut = new CTrieSubscriptionDirectory();
MemoryStorageService memStore = new MemoryStorageService(null, null);
ISessionsStore aSessionsStore = memStore.sessionsStore();
SessionsRepository sessionsRepository = new SessionsRepository(aSessionsStore, null);
ISubscriptionsRepository sessionsRepository = new MemorySubscriptionsRepository();
sut.init(sessionsRepository);
}
@@ -16,7 +16,6 @@
package io.moquette.testclient;
import io.moquette.server.netty.NettyMQTTHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -29,7 +28,7 @@ import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
@ChannelHandler.Sharable
class ClientNettyMQTTHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(NettyMQTTHandler.class);
private static final Logger LOG = LoggerFactory.getLogger(ClientNettyMQTTHandler.class);
private Client m_client;
@Override