blob: bef02b9dd9efc696687494c7e3c703daaf4788af [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.vysper.xmpp.modules.extension.xep0313_mam.user;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.apache.vysper.xmpp.modules.extension.xep0313_mam.IntegrationTest;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.jivesoftware.smackx.forward.packet.Forwarded;
import org.jivesoftware.smackx.mam.MamManager;
import org.jivesoftware.smackx.mam.element.MamPrefsIQ;
import org.jivesoftware.smackx.sid.element.StableAndUniqueIdElement;
import org.jivesoftware.smackx.sid.element.StanzaIdElement;
import org.junit.Test;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
/**
* @author RĂ©da Housni Alaoui
*/
public class UserArchiveTest extends IntegrationTest {
@Test
public void queryEmptyArchive()
throws XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException,
SmackException.NotLoggedInException, SmackException.NoResponseException {
MamManager.MamQueryArgs mamQueryArgs = MamManager.MamQueryArgs.builder().build();
MamManager.MamQuery mamQuery = MamManager.getInstanceFor(alice()).queryArchive(mamQueryArgs);
assertEquals(0, mamQuery.getMessageCount());
}
@Test
public void sendMessageAndQuerySenderAndReceiverArchive()
throws SmackException.NotConnectedException, InterruptedException, SmackException.NotLoggedInException,
XMPPException.XMPPErrorException, SmackException.NoResponseException {
AtomicReference<Message> carolReceivedMessage = new AtomicReference<>();
ChatManager.getInstanceFor(carol()).addIncomingListener((from, message, chat) -> {
carolReceivedMessage.set(message);
});
Chat chat = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
chat.send("Hello carol");
MamManager.MamQueryArgs fullQuery = MamManager.MamQueryArgs.builder().build();
MamManager.MamQuery aliceArchive = MamManager.getInstanceFor(alice()).queryArchive(fullQuery);
assertEquals(1, aliceArchive.getMessageCount());
Message toCarolArchivedMessage = aliceArchive.getMessages().get(0);
assertEquals("Hello carol", toCarolArchivedMessage.getBody());
assertEquals(alice().getUser(), toCarolArchivedMessage.getFrom());
assertEquals(carol().getUser().asEntityBareJidOrThrow(),
toCarolArchivedMessage.getTo().asEntityBareJidOrThrow());
String toCarolArchivedMessageId = extractStanzaId(toCarolArchivedMessage);
MamManager.MamQuery carolArchive = MamManager.getInstanceFor(carol()).queryArchive(fullQuery);
assertEquals(1, carolArchive.getMessageCount());
Message fromAliceArchivedMessage = carolArchive.getMessages().get(0);
assertEquals("Hello carol", fromAliceArchivedMessage.getBody());
assertEquals(alice().getUser(), fromAliceArchivedMessage.getFrom());
assertEquals(carol().getUser().asEntityBareJidOrThrow(),
fromAliceArchivedMessage.getTo().asEntityBareJidOrThrow());
String fromAliceArchivedMessageId = extractStanzaId(fromAliceArchivedMessage);
assertFalse(toCarolArchivedMessageId.equals(fromAliceArchivedMessageId));
assertEquals(extractStanzaId(carolReceivedMessage.get()), fromAliceArchivedMessageId);
}
@Test
public void checkSorting() throws SmackException.NotConnectedException, InterruptedException,
SmackException.NotLoggedInException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
Chat chat = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
for (int index = 1; index <= 10; index++) {
chat.send("Hello " + index);
}
MamManager.MamQueryArgs fullQuery = MamManager.MamQueryArgs.builder().build();
MamManager.MamQuery aliceArchive = MamManager.getInstanceFor(alice()).queryArchive(fullQuery);
assertEquals(10, aliceArchive.getMessageCount());
assertTrue(aliceArchive.isComplete());
for (int index = 1; index <= 10; index++) {
assertEquals("Hello " + index, aliceArchive.getMessages().get(index - 1).getBody());
}
}
@Test
public void paginate() throws SmackException.NotConnectedException, InterruptedException,
SmackException.NotLoggedInException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
Chat chat = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
for (int index = 1; index <= 10; index++) {
chat.send("Hello " + index);
}
MamManager mamManager = MamManager.getInstanceFor(alice());
MamManager.MamQueryArgs firstHalfPageable = MamManager.MamQueryArgs.builder().setResultPageSizeTo(5).build();
MamManager.MamQuery page = mamManager.queryArchive(firstHalfPageable);
assertFalse(page.isComplete());
assertEquals(5, page.getMessageCount());
for (int index = 1; index <= 5; index++) {
assertEquals("Hello " + index, page.getMessages().get(index - 1).getBody());
}
page.pageNext(5);
assertFalse(page.isComplete());
assertEquals(5, page.getMessageCount());
for (int index = 6; index <= 10; index++) {
assertEquals("Hello " + index, page.getMessages().get(index - 6).getBody());
}
}
@Test
public void lastPage() throws SmackException.NotConnectedException, InterruptedException,
SmackException.NotLoggedInException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
Chat chat = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
for (int index = 1; index <= 10; index++) {
chat.send("Hello " + index);
}
MamManager mamManager = MamManager.getInstanceFor(alice());
MamManager.MamQuery fullQuery = mamManager.queryArchive(MamManager.MamQueryArgs.builder().build());
List<String> allMessageIds = fullQuery.getPage().getForwarded().stream().map(Forwarded::getForwardedStanza)
.map(stanza -> stanza.getExtension("stanza-id", NamespaceURIs.XEP0359_STANZA_IDS))
.map(StanzaIdElement.class::cast).map(StableAndUniqueIdElement::getId).collect(Collectors.toList());
String lastMessageUid = mamManager.getMessageUidOfLatestMessage();
assertEquals(allMessageIds.get(allMessageIds.size() - 1), lastMessageUid);
}
@Test
public void givenOfflineStorageSendMessageToOfflineReceiver()
throws SmackException, InterruptedException, XMPPException, IOException {
carol().instantShutdown();
Chat chatFromAliceToCarol = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
chatFromAliceToCarol.send("Hello carol");
AtomicReference<Message> carolReceivedMessage = new AtomicReference<>();
ChatManager.getInstanceFor(carol())
.addIncomingListener((from, message, chat) -> carolReceivedMessage.set(message));
carol().connect();
carol().login();
Thread.sleep(200);
assertNotNull(carolReceivedMessage.get());
assertEquals("Hello carol", carolReceivedMessage.get().getBody());
Message archivedMessage = fetchUniqueArchivedMessage(carol());
String storedStanzaId = extractStanzaId(archivedMessage);
assertNotNull(storedStanzaId);
String receivedStanzaId = extractStanzaId(carolReceivedMessage.get());
assertEquals(storedStanzaId, receivedStanzaId);
}
@Test
public void givenDisabledOfflineStorageSendMessageToOfflineReceiver()
throws SmackException, InterruptedException, XMPPException, IOException {
offlineStorageProvider().disable();
carol().instantShutdown();
Chat chatFromAliceToCarol = ChatManager.getInstanceFor(alice()).chatWith(carol().getUser().asEntityBareJid());
chatFromAliceToCarol.send("Hello carol");
AtomicReference<Message> carolReceivedMessage = new AtomicReference<>();
ChatManager.getInstanceFor(carol())
.addIncomingListener((from, message, chat) -> carolReceivedMessage.set(message));
carol().connect();
carol().login();
Thread.sleep(200);
assertNotNull(carolReceivedMessage.get());
assertEquals("Hello carol", carolReceivedMessage.get().getBody());
Message archivedMessage = fetchUniqueArchivedMessage(carol());
String storedStanzaId = extractStanzaId(archivedMessage);
assertNotNull(storedStanzaId);
String receivedStanzaId = extractStanzaId(carolReceivedMessage.get());
assertEquals(storedStanzaId, receivedStanzaId);
}
@Test
public void getPreferences() throws SmackException.NotLoggedInException, SmackException.NotConnectedException,
InterruptedException, SmackException.NoResponseException, XMPPException.XMPPErrorException {
MamManager mamManager = MamManager.getInstanceFor(alice());
MamManager.MamPrefsResult prefsResult = mamManager.retrieveArchivingPreferences();
MamManager.MamPrefs mamPrefs = prefsResult.asMamPrefs();
assertEquals(MamPrefsIQ.DefaultBehavior.always, mamPrefs.getDefaultBehavior());
assertTrue(mamPrefs.getAlwaysJids().isEmpty());
assertTrue(mamPrefs.getNeverJids().isEmpty());
}
@Test
public void setPreferences() throws XMPPException.XMPPErrorException, SmackException.NotLoggedInException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
XmppStringprepException {
MamManager mamManager = MamManager.getInstanceFor(alice());
MamManager.MamPrefsResult prefsResult = mamManager.retrieveArchivingPreferences();
MamManager.MamPrefs prefs = prefsResult.asMamPrefs();
prefs.setDefaultBehavior(MamPrefsIQ.DefaultBehavior.never);
prefs.getAlwaysJids().add(JidCreate.bareFrom("always@foo.com"));
prefs.getNeverJids().add(JidCreate.bareFrom("never@foo.com"));
MamManager.MamPrefsResult updatedPrefsResult = mamManager.updateArchivingPreferences(prefs);
MamManager.MamPrefs updatedPrefs = updatedPrefsResult.asMamPrefs();
assertEquals(MamPrefsIQ.DefaultBehavior.never, updatedPrefs.getDefaultBehavior());
List<Jid> alwaysJids = updatedPrefs.getAlwaysJids();
assertEquals(1, alwaysJids.size());
assertEquals(JidCreate.bareFrom("always@foo.com"), alwaysJids.get(0));
List<Jid> neverJids = updatedPrefs.getNeverJids();
assertEquals(1, neverJids.size());
assertEquals(JidCreate.bareFrom("never@foo.com"), neverJids.get(0));
}
@Test
public void discoverInfo() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException,
InterruptedException, SmackException.NoResponseException {
ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(alice());
DiscoverInfo discoverInfo = discoveryManager.discoverInfo(alice().getUser().asBareJid());
List<DiscoverInfo.Feature> features = discoverInfo.getFeatures();
boolean mamV1Enabled = features.stream().map(DiscoverInfo.Feature::getVar).anyMatch("urn:xmpp:mam:1"::equals);
assertTrue(mamV1Enabled);
boolean mamV2Enabled = features.stream().map(DiscoverInfo.Feature::getVar).anyMatch("urn:xmpp:mam:2"::equals);
assertTrue(mamV2Enabled);
}
private Message fetchUniqueArchivedMessage(AbstractXMPPConnection connection)
throws XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException,
SmackException.NotLoggedInException, SmackException.NoResponseException {
MamManager.MamQueryArgs archiveFullQuery = MamManager.MamQueryArgs.builder().build();
MamManager.MamQuery archive = MamManager.getInstanceFor(connection).queryArchive(archiveFullQuery);
assertEquals(1, archive.getMessageCount());
return archive.getMessages().get(0);
}
private String extractStanzaId(Stanza stanza) {
assertNotNull(stanza);
ExtensionElement extensionElement = stanza.getExtension(NamespaceURIs.XEP0359_STANZA_IDS);
if (!(extensionElement instanceof StanzaIdElement)) {
fail("No stanza id in " + stanza);
}
return ((StanzaIdElement) extensionElement).getId();
}
}