/*
* Copyright (C) 2017-2023 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dom.io;
import org.dom4j.Document;
import org.dom4j.Namespace;
import org.dom4j.io.XMPPPacketReader;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.xmlpull.v1.XmlPullParser;
import java.io.StringReader;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.*;
/**
* Unit tests that verify the functionality of {@link XMPPPacketReader}
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class XMPPPacketReaderTest
{
private XMPPPacketReader packetReader;
@BeforeEach
public void setup()
{
packetReader = new XMPPPacketReader();
}
/**
* Check if the 'jabber:client' default namespace declaration is stripped from a stream tag.
*
* Openfire strips this namespace (among others) to make the resulting XML 're-usable', in context of the
* implementation note in RFC 6120, section 4.8.3.
*
* @see RFC 6120, 4.8.3. XMPP Content Namespaces
*/
@Test
public void testStripContentNamespace() throws Exception
{
// Setup fixture.
final String input = "Art thou not Romeo, and a Montague?";
// Execute system under test.
final Document result = packetReader.read( new StringReader( input ) );
// Verify result.
assertFalse( result.asXML().contains( "jabber:client" ) );
}
/**
* Check if the 'jabber:client' default namespace declaration is stripped from a stanza.
*
* Openfire strips this namespace (among others) to make the resulting XML 're-usable', in context of the
* implementation note in RFC 6120, section 4.8.3.
*
* @see RFC 6120, 4.8.3. XMPP Content Namespaces
*/
@Test
public void testStripPrefixFreeCanonicalization() throws Exception
{
// Setup fixture.
final String input = "Art thou not Romeo, and a Montague?";
// Execute system under test.
final Document result = packetReader.read( new StringReader( input ) );
// Verify result.
assertFalse( result.asXML().contains( "jabber:client" ) );
}
/**
* Check that the 'jabber:client' default namespace declaration is explicitly _not_ stripped from a child element
* of a stanza.
*
* Openfire strips this namespace (among others) to make the resulting XML 're-usable', in context of the
* implementation note in RFC 6120, section 4.8.3.
*
* @see Issue OF-1335: Forwarded messages rewritten to default namespace over S2S
* @see RFC 6120, 4.8.3. XMPP Content Namespaces
*/
@Test
public void testAvoidStrippingInternalContentNamespace() throws Exception
{
// Setup fixture
final String input =
"" +
" " +
" " +
" " +
" " +
" " +
"";
final Document result = packetReader.read( new StringReader( input ) );
// Verify result.
assertFalse( result.asXML().substring( 0, result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should not occur before 'something:else'" );
assertTrue( result.asXML().substring( result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should occur after 'something:else'" );
}
/**
* Check that the 'jabber:client' default namespace declaration is explicitly _not_ stripped from a child element
* of a stanza.
*
* Openfire strips this namespace (among others) to make the resulting XML 're-usable', in context of the
* implementation note in RFC 6120, section 4.8.3.
*
* @see Issue OF-1335: Forwarded messages rewritten to default namespace over S2S
* @see RFC 6120, 4.8.3. XMPP Content Namespaces
*/
@Test
public void testAvoidStrippingPrefixFreeCanonicalization() throws Exception
{
// Setup fixture
final String input =
"" +
" " +
" " +
" " +
" " +
" " +
"";
final Document result = packetReader.read( new StringReader( input ) );
// Verify result.
assertFalse( result.asXML().substring( 0, result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should not occur before 'something:else'" );
assertTrue( result.asXML().substring( result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should occur after 'something:else'" );
}
/**
* Check that a websocket connection would also work.
*/
@Test
public void testStripNamespacesForWebsocket() throws Exception
{
final String input_header = "";
final Document doc_header = packetReader.read( new StringReader( input_header ) );
final String input = " " +
" " +
" " +
" " +
" ";
final Document result = packetReader.read( new StringReader( input ) );
// Verify result.
assertFalse( result.asXML().substring( 0, result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should not occur before 'something:else'" );
assertTrue( result.asXML().substring( result.asXML().indexOf("something:else") ).contains( "jabber:client" ), "'jabber:client' should occur after 'something:else'" );
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} returns a prefix and
* namespace declaration on the element that the parser is currently on.
*/
@Test
public void test_GetNamespacesOnCurrentElement_CustomNamespace() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"message".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(1, namespacesOnCurrentElement.size());
assertEquals(Namespace.get("unittest", "custom:namespace"), namespacesOnCurrentElement.iterator().next());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} returns a prefix and
* namespace declaration on the element that the parser is currently on.
*/
@Test
public void test_GetNamespacesOnCurrentElement_XmlLang() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"message".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(0, namespacesOnCurrentElement.size());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} does not return a
* default namespace declaration on the element that the parser is currently on.
*/
@Test
public void test_GetNamespacesOnCurrentElement_DefaultNamespace() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"message".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(0, namespacesOnCurrentElement.size());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} does not return a
* prefix and namespace declaration on the element that the parser is currently on, if the namespace matches one of
* the namespaces in {@link XMPPPacketReader#IGNORED_NAMESPACE_ON_STANZA}.
*/
@Test
public void test_GetNamespacesOnCurrentElement_IgnoredNamespace() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"message".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(0, namespacesOnCurrentElement.size());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} does not return a
* prefix and namespace declaration on the element that the parser is currently on, if the namespace matches one of
* the 'http://etherx.jabber.org/streams' namespace.
*/
@Test
public void test_GetNamespacesOnCurrentElement_IgnoredStreamNamespace() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"message".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(0, namespacesOnCurrentElement.size());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} only returns a prefix
* and namespace declaration on the element that the parser is currently on, when that element also declares data
* that is to be ignored.
*/
@Test
public void test_GetNamespacesOnCurrentElement_MixedNamespace() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"stream".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(1, namespacesOnCurrentElement.size());
assertEquals(Namespace.get("unittest", "custom:namespace"), namespacesOnCurrentElement.iterator().next());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} does not return data
* that is declared on a child element of the element that the parser is currently on.
*/
@Test
public void test_GetNamespacesOnCurrentElement_MixedNamespace_WithChildElement() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "" +
" " +
"";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to the root element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"stream".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(1, namespacesOnCurrentElement.size());
assertEquals(Namespace.get("unittest", "custom:namespace"), namespacesOnCurrentElement.iterator().next());
}
/**
* Verify that {@link XMPPPacketReader#getPrefixedNamespacesOnCurrentElement(XmlPullParser)} does not return data
* that is declared on a parent element of the element that the parser is currently on.
*/
@Test
public void test_GetNamespacesOnCurrentElement_MixedNamespace_OnChildElement() throws Exception
{
// Setup test fixture.
packetReader.getXPPParser().resetInput();
final String input = "" +
" " +
"";
packetReader.getXPPParser().setInput(new StringReader(input));
int type;
do { // Progress parsing to CHILD element.
type = packetReader.getXPPParser().next();
} while (type != XmlPullParser.START_TAG || !"child".equals(packetReader.getXPPParser().getName()));
// Execute system under test.
final Set namespacesOnCurrentElement = XMPPPacketReader.getPrefixedNamespacesOnCurrentElement(packetReader.getXPPParser());
// Verify results.
assertEquals(1, namespacesOnCurrentElement.size());
assertEquals(Namespace.get("unittest", "custom:namespace"), namespacesOnCurrentElement.iterator().next());
}
}