Removed all the old ProtocolProcessor stuff
This commit is contained in:
@@ -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;
|
||||
|
||||
+4
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
-191
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
-363
@@ -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());
|
||||
// }
|
||||
|
||||
}
|
||||
+10
-26
@@ -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);
|
||||
|
||||
|
||||
+3
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user