2018-04-25 19:39:12 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2012-2017 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-04-20 23:14:23 +02:00
|
|
|
package io.moquette.persistence;
|
|
|
|
|
|
|
|
|
|
import io.moquette.spi.*;
|
|
|
|
|
import io.moquette.spi.IMessagesStore.StoredMessage;
|
2017-09-12 19:48:42 +02:00
|
|
|
import io.moquette.spi.impl.SessionsRepository;
|
2017-04-20 23:14:23 +02:00
|
|
|
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;
|
|
|
|
|
|
2018-04-25 19:39:12 +02:00
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
2017-04-20 23:14:23 +02:00
|
|
|
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;
|
2018-04-25 19:39:12 +02:00
|
|
|
import static java.nio.charset.StandardCharsets.*;
|
2017-04-20 23:14:23 +02:00
|
|
|
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;
|
2017-09-12 19:48:42 +02:00
|
|
|
protected SessionsRepository sessionsRepository;
|
2017-04-20 23:14:23 +02:00
|
|
|
|
|
|
|
|
@Test
|
2018-04-25 19:39:12 +02:00
|
|
|
public void testDropMessagesInSessionDoesntCleanAnyRetainedStoredMessages() throws UnsupportedEncodingException {
|
2017-09-12 19:48:42 +02:00
|
|
|
final ClientSession session = sessionsRepository.createNewSession(TEST_CLIENT, true);
|
2018-04-25 19:39:12 +02:00
|
|
|
StoredMessage publishToStore = new StoredMessage("Hello".getBytes(UTF_8), EXACTLY_ONCE, "/topic");
|
2017-04-20 23:14:23 +02:00
|
|
|
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
|
2018-04-25 19:39:12 +02:00
|
|
|
public void testStoreRetained() throws UnsupportedEncodingException {
|
|
|
|
|
StoredMessage msgStored = new StoredMessage("Hello".getBytes(UTF_8), MqttQoS.AT_LEAST_ONCE, "/topic");
|
2017-04-20 23:14:23 +02:00
|
|
|
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);
|
2018-04-25 19:39:12 +02:00
|
|
|
assertEquals("Hello", new String(content, UTF_8));
|
2017-04-20 23:14:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void givenSubscriptionAlreadyStoredIsOverwrittenByAnotherWithSameTopic() {
|
2017-09-12 19:48:42 +02:00
|
|
|
ClientSession session1 = sessionsRepository.createNewSession("SESSION_ID_1", false);
|
2017-04-20 23:14:23 +02:00
|
|
|
|
|
|
|
|
// 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();
|
2017-09-12 19:48:42 +02:00
|
|
|
List<Subscription> subscriptions = subscriptionsStore.listAllSubscriptions();
|
2017-04-20 23:14:23 +02:00
|
|
|
assertEquals(1, subscriptions.size());
|
2017-09-12 19:48:42 +02:00
|
|
|
Subscription sub = subscriptions.get(0);
|
2017-04-20 23:14:23 +02:00
|
|
|
assertEquals(overridingSubscription.getRequestedQos(), sub.getRequestedQos());
|
|
|
|
|
}
|
|
|
|
|
}
|