1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-26 00:02:06 +01:00

Add initializer tests and move classpath files

The initializer tests verify that every non-optional initializer, this
includes Providers, is loadable.

Creating files under META-INF is not considered best practice. Smack's
configuration and provider files reside now in classpath directory
qualified by Smack's package namespace.
This commit is contained in:
Florian Schmaus 2014-02-15 13:01:57 +01:00
parent 8d3814a8a7
commit 2ad517b6dd
30 changed files with 411 additions and 141 deletions

View file

@ -220,6 +220,24 @@ Smack core components.
compression compressionJar
dns dnsJar
}
task createVersionResource(type: CreateFileTask) {
fileContent = version
outputFile = new File(projectDir, 'src/main/resources/org.jivesoftware.smack/version')
}
compileJava.dependsOn(createVersionResource)
}
class CreateFileTask extends DefaultTask {
@Input
String fileContent
@OutputFile
File outputFile
@TaskAction
def createFile() {
outputFile.text = fileContent
}
}
project(':compression-jzlib') {

1
core/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
src/main/resources/org.jivesoftware.smack/version

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smack;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -26,11 +27,13 @@ import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
import org.jivesoftware.smack.util.FileUtils;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* Represents the configuration of Smack. The configuration is used for:
@ -42,21 +45,20 @@ import org.xmlpull.v1.XmlPullParser;
* via the API will override settings in the configuration file.
* </ul>
*
* Configuration settings are stored in META-INF/smack-config.xml (typically inside the
* Configuration settings are stored in org.jivesoftware.smack/smack-config.xml (typically inside the
* smack.jar file).
*
* @author Gaston Dombiak
*/
public final class SmackConfiguration {
private static final String SMACK_VERSION = "3.4.0";
private static final String DEFAULT_CONFIG_FILE = "classpath:META-INF/smack-config.xml";
private static final String SMACK_VERSION;
private static final String DEFAULT_CONFIG_FILE = "classpath:org.jivesoftware.smack/smack-config.xml";
private static final Logger log = Logger.getLogger(SmackConfiguration.class.getName());
private static InputStream configFileStream;
private static int packetReplyTimeout = 5000;
private static int keepAliveInterval = 30000;
private static List<String> defaultMechs = new ArrayList<String>();
private static boolean localSocks5ProxyEnabled = true;
@ -65,6 +67,20 @@ public final class SmackConfiguration {
private static boolean initialized = false;
static {
String smackVersion;
try {
InputStream is = FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null);
byte[] buf = new byte[1024];
is.read(buf);
smackVersion = new String(buf, Charset.forName("UTF-8"));
} catch(Exception e) {
log.log(Level.SEVERE, "Could not determine Smack version", e);
smackVersion = "unkown";
}
SMACK_VERSION = smackVersion;
}
/**
* The default parsing exception callback is {@link ExceptionThrowingCallback} which will
* throw an exception and therefore disconnect the active connection.
@ -88,7 +104,7 @@ public final class SmackConfiguration {
*/
/**
* Sets the location of the config file on the classpath. Only required if changing from the default location of <i>classpath:META-INF/smack-config.xml</i>.
* Sets the location of the config file on the classpath. Only required if changing from the default location of <i>classpath:org.jivesoftware.smack/smack-config.xml</i>.
*
* <p>
* This method must be called before accessing any other class in Smack.
@ -320,8 +336,21 @@ public final class SmackConfiguration {
return defaultCallback;
}
private static void parseClassToLoad(XmlPullParser parser) throws Exception {
String className = parser.nextText();
public static void parseClassesToLoad(XmlPullParser parser, boolean optional) throws XmlPullParserException, IOException, Exception {
final String startName = parser.getName();
int eventType;
String name;
do {
eventType = parser.next();
name = parser.getName();
if (eventType == XmlPullParser.START_TAG && "className".equals(name)) {
String classToLoad = parser.nextText();
loadSmackClass(classToLoad, optional);
}
} while (! (eventType == XmlPullParser.END_TAG && startName.equals(name)));
}
public static void loadSmackClass(String className, boolean optional) throws Exception {
// Attempt to load the class so that the class can get initialized
try {
Class<?> initClass = Class.forName(className);
@ -332,7 +361,17 @@ public final class SmackConfiguration {
}
}
catch (ClassNotFoundException cnfe) {
log.log(Level.WARNING, "A startup class [" + className + "] specified in smack-config.xml could not be loaded: ");
Level logLevel;
if (optional) {
logLevel = Level.FINE;
}
else {
logLevel = Level.WARNING;
}
log.log(logLevel, "A startup class [" + className
+ "] specified in smack-config.xml could not be loaded: ");
if (!optional)
throw cnfe;
}
}
@ -373,36 +412,39 @@ public final class SmackConfiguration {
configFileStream = FileUtils.getStreamForUrl(DEFAULT_CONFIG_FILE, null);
}
catch (Exception e) {
log.log(Level.INFO, "Could not create input stream for default config file [" + DEFAULT_CONFIG_FILE + "]", e);
throw new IllegalStateException(e);
}
}
if (configFileStream != null) {
try {
readFile(configFileStream);
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}
else {
log.log(Level.INFO, "No configuration file found");
}
}
private static void readFile(InputStream cfgFileStream) {
try {
private static void readFile(InputStream cfgFileStream) throws Exception {
XmlPullParser parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(cfgFileStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("className")) {
// Attempt to load the class so that the class can get initialized
parseClassToLoad(parser);
if (parser.getName().equals("startupClasses")) {
parseClassesToLoad(parser, false);
}
else if (parser.getName().equals("optionalStartupClasses")) {
parseClassesToLoad(parser, true);
}
else if (parser.getName().equals("packetReplyTimeout")) {
packetReplyTimeout = parseIntProperty(parser, packetReplyTimeout);
}
else if (parser.getName().equals("keepAliveInterval")) {
keepAliveInterval = parseIntProperty(parser, keepAliveInterval);
}
else if (parser.getName().equals("mechName")) {
defaultMechs.add(parser.nextText());
}
@ -420,16 +462,13 @@ public final class SmackConfiguration {
}
}
eventType = parser.next();
} while (eventType != XmlPullParser.END_DOCUMENT);
} catch (Exception e) {
log.log(Level.SEVERE, "Error occurred while reading config file", e);
}
finally {
while (eventType != XmlPullParser.END_DOCUMENT);
try {
cfgFileStream.close();
} catch (IOException e) {
log.log(Level.INFO, "Error while closing config file input stream", e);
}
}
catch (IOException e) {
log.log(Level.SEVERE, "Error while closing config file input stream", e);
}
}
}

View file

@ -1,6 +1,5 @@
package org.jivesoftware.smack.provider;
package org.jivesoftware.smack.initializer;
import org.jivesoftware.smack.SmackInitializer;
/**
* Loads the default provider file for the Smack core on initialization.
@ -10,6 +9,6 @@ import org.jivesoftware.smack.SmackInitializer;
*/
public class CoreInitializer extends UrlProviderFileInitializer implements SmackInitializer {
protected String getFilePath() {
return "classpath:META-INF/core.providers";
return "classpath:org.jivesoftware.smack/core.providers";
}
}

View file

@ -1,5 +1,8 @@
package org.jivesoftware.smack;
package org.jivesoftware.smack.initializer;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
@ -16,13 +19,21 @@ public class LoggingInitializer implements SmackInitializer {
private static Logger log = Logger.getLogger(LoggingInitializer.class.getName());
private List<Exception> exceptions = new LinkedList<Exception>();
@Override
public void initialize() {
try {
LogManager.getLogManager().readConfiguration(FileUtils.getStreamForUrl("classpath:META-INF/jul.properties", null));
LogManager.getLogManager().readConfiguration(FileUtils.getStreamForUrl("classpath:org.jivesofware.smack/jul.properties", null));
}
catch (Exception e) {
log .log(Level.WARNING, "Could not initialize Java Logging from default file.", e);
exceptions.add(e);
}
}
@Override
public List<Exception> getExceptions() {
return Collections.unmodifiableList(exceptions);
}
}

View file

@ -1,4 +1,8 @@
package org.jivesoftware.smack;
package org.jivesoftware.smack.initializer;
import java.util.List;
import org.jivesoftware.smack.SmackConfiguration;
/**
* Defines an initialization class that will be instantiated and invoked by the {@link SmackConfiguration} class during initialization.
@ -11,4 +15,5 @@ package org.jivesoftware.smack;
*/
public interface SmackInitializer {
void initialize();
List<Exception> getExceptions();
}

View file

@ -1,15 +1,19 @@
package org.jivesoftware.smack.provider;
package org.jivesoftware.smack.initializer;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackInitializer;
import org.jivesoftware.smack.provider.ProviderFileLoader;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.FileUtils;
/**
@ -21,6 +25,8 @@ import org.jivesoftware.smack.util.FileUtils;
public abstract class UrlProviderFileInitializer implements SmackInitializer {
private static final Logger log = Logger.getLogger(UrlProviderFileInitializer.class.getName());
private List<Exception> exceptions = new LinkedList<Exception>();
@Override
public void initialize() {
String filePath = getFilePath();
@ -30,17 +36,26 @@ public abstract class UrlProviderFileInitializer implements SmackInitializer {
if (is != null) {
log.log(Level.INFO, "Loading providers for file [" + filePath + "]");
ProviderManager.getInstance().addLoader(new ProviderFileLoader(is));
ProviderFileLoader pfl = new ProviderFileLoader(is);
ProviderManager.getInstance().addLoader(pfl);
exceptions.addAll(pfl.getLoadingExceptions());
}
else {
log.log(Level.WARNING, "No input stream created for " + filePath);
exceptions.add(new IOException("No input stream created for " + filePath));
}
}
catch (Exception e) {
log.log(Level.SEVERE, "Error trying to load provider file " + filePath, e);
exceptions.add(e);
}
}
@Override
public List<Exception> getExceptions() {
return Collections.unmodifiableList(exceptions);
}
protected abstract String getFilePath();
/**

View file

@ -1,4 +1,6 @@
package org.jivesoftware.smack.provider;
package org.jivesoftware.smack.initializer;
import org.jivesoftware.smack.provider.ProviderManager;
/**

View file

@ -3,6 +3,9 @@ package org.jivesoftware.smack.provider;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -24,6 +27,7 @@ public class ProviderFileLoader implements ProviderLoader {
private Collection<IQProviderInfo> iqProviders;
private Collection<ExtensionProviderInfo> extProviders;
private InputStream providerStream;
private List<Exception> exceptions = new LinkedList<Exception>();
public ProviderFileLoader(InputStream providerFileInputStream) {
setInputStream(providerFileInputStream);
@ -44,6 +48,10 @@ public class ProviderFileLoader implements ProviderLoader {
return extProviders;
}
public List<Exception> getLoadingExceptions() {
return Collections.unmodifiableList(exceptions);
}
@SuppressWarnings("unchecked")
private synchronized void initialize() {
// Check to see if already initialized
@ -112,11 +120,13 @@ public class ProviderFileLoader implements ProviderLoader {
}
catch (ClassNotFoundException cnfe) {
log.log(Level.SEVERE, "Could not find provider class", cnfe);
exceptions.add(cnfe);
}
}
}
catch (IllegalArgumentException illExc) {
log.log(Level.SEVERE, "Invalid provider type found [" + typeName + "] when expecting iqProvider or extensionProvider", illExc);
exceptions.add(illExc);
}
}
eventType = parser.next();

View file

@ -41,7 +41,7 @@ import org.jivesoftware.smack.packet.IQ;
*
* Because many more IQ types are part of XMPP and its extensions, a pluggable IQ parsing
* mechanism is provided. IQ providers are registered programatically or by creating a
* smack.providers file in the META-INF directory of your JAR file. The file is an XML
* providers file. The file is an XML
* document that contains one or more iqProvider entries, as in the following example:
*
* <pre>

View file

@ -9,11 +9,4 @@
<className>org.jivesoftware.smack.provider.PrivacyProvider</className>
</iqProvider>
<!-- Ping (XEP-199) Manager -->
<iqProvider>
<elementName>ping</elementName>
<namespace>urn:xmpp:ping</namespace>
<className>org.jivesoftware.smack.ping.provider.PingProvider</className>
</iqProvider>
</smackProviders>

View file

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!-- Smack configuration file. -->
<smack>
<!-- Packet reply timeout in milliseconds -->
<packetReplyTimeout>5000</packetReplyTimeout>
<!-- Enable/Disable local Socks5 proxy -->
<localSocks5ProxyEnabled>true</localSocks5ProxyEnabled>
<!-- Port of the local Socks5 proxy -->
<localSocks5ProxyPort>7777</localSocks5ProxyPort>
<!-- Port of the local Socks5 proxy -->
<packetCollectorSize>10000</packetCollectorSize>
<!-- Automatic enable Entity Caps (XEP-0115) for new connections -->
<autoEnableEntityCaps>false</autoEnableEntityCaps>
<!-- Classes that will be loaded when Smack starts -->
<startupClasses>
<className>org.jivesoftware.smack.initializer.CoreInitializer</className>
<className>org.jivesoftware.smack.initializer.VmArgInitializer</className>
<className>org.jivesoftware.smack.PrivacyListManager</className>
<className>org.jivesoftware.smack.ReconnectionManager</className>
</startupClasses>
<optionalStartupClasses>
<className>org.jivesoftware.smack.util.dns.JavaxResolver</className>
<className>org.jivesoftware.smackx.ExtensionsProviderInitializer</className>
<className>org.jivesoftware.smackx.ExtensionsStartupClasses</className>
<className>org.jivesoftware.smackx.ExperimentalProviderInitializer</className>
<className>org.jivesoftware.smackx.WorkgroupProviderInitializer</className>
</optionalStartupClasses>
</smack>

View file

@ -1,39 +0,0 @@
<?xml version="1.0"?>
<!-- Smack configuration file. -->
<smack>
<!-- Packet reply timeout in milliseconds -->
<packetReplyTimeout>5000</packetReplyTimeout>
<!-- Enable/Disable local Socks5 proxy -->
<localSocks5ProxyEnabled>true</localSocks5ProxyEnabled>
<!-- Port of the local Socks5 proxy -->
<localSocks5ProxyPort>7777</localSocks5ProxyPort>
<!-- Port of the local Socks5 proxy -->
<packetCollectorSize>10000</packetCollectorSize>
<!-- Automatic enable Entity Caps (XEP-0115) for new connections -->
<autoEnableEntityCaps>false</autoEnableEntityCaps>
<!-- Classes that will be loaded when Smack starts -->
<startupClasses>
<className>org.jivesoftware.smack.provider.CoreInitializer</className>
<className>org.jivesoftware.smack.provider.VmArgInitializer</className>
<className>org.jivesoftware.smack.PrivacyListManager</className>
<className>org.jivesoftware.smackx.ExtensionInitializer</className>
<className>org.jivesoftware.smackx.disco.ServiceDiscoveryManager</className>
<className>org.jivesoftware.smackx.xhtmlim.XHTMLManager</className>
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
<className>org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager</className>
<className>org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager</className>
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
<className>org.jivesoftware.smackx.iqlast.LastActivityManager</className>
<className>org.jivesoftware.smack.ReconnectionManager</className>
<className>org.jivesoftware.smackx.commands.AdHocCommandManager</className>
<className>org.jivesoftware.smack.util.dns.JavaxResolver</className>
<className>org.jivesoftware.smackx.ping.PingManager</className>
</startupClasses>
</smack>

View file

@ -0,0 +1,17 @@
package org.jivesoftware.smack;
import static org.junit.Assert.fail;
import org.junit.Test;
public class SmackConfigurationTest {
@Test
public void testSmackConfiguration() {
try {
SmackConfiguration.getPacketReplyTimeout();
} catch (Throwable t) {
fail("SmackConfiguration threw Throwable");
}
}
}

View file

@ -0,0 +1,17 @@
package org.jivesoftware.smack.initializer;
import static org.junit.Assert.assertTrue;
import org.jivesoftware.smack.initializer.CoreInitializer;
import org.junit.Test;
public class CoreInitializerTest {
@Test
public void testCoreInitializer() {
CoreInitializer ci = new CoreInitializer();
ci.initialize();
assertTrue(ci.getExceptions().size() == 0);
}
}

View file

@ -14,9 +14,9 @@
* limitations under the License.
*/
package org.jivesoftware.smackx.experimental;
package org.jivesoftware.smackx;
import org.jivesoftware.smack.provider.UrlProviderFileInitializer;
import org.jivesoftware.smack.initializer.UrlProviderFileInitializer;
/**
* Initializes the providers in the experimental code stream.
@ -28,6 +28,6 @@ public class ExperimentalProviderInitializer extends UrlProviderFileInitializer
@Override
protected String getFilePath() {
return "classpath:META-INF/experimental.providers";
return "classpath:org.jivesoftware.smackx/experimental.providers";
}
}

View file

@ -0,0 +1,11 @@
package org.jivesoftware.smackx;
import org.jivesoftware.smack.initializer.UrlProviderFileInitializer;
public class WorkgroupProviderInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:org.jivesoftware.smackx/workgroup.providers";
}
}

View file

@ -1,11 +0,0 @@
package org.jivesoftware.smackx.workgroup;
import org.jivesoftware.smack.provider.UrlProviderFileInitializer;
public class WorkgroupProviderInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:META-INF/workgroup.providers";
}
}

View file

@ -0,0 +1,15 @@
package org.jivesoftware.smackx;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ExperimentalProviderInitializerTest {
@Test
public void testExperimentalProviderInitialzer() {
ExperimentalProviderInitializer epi = new ExperimentalProviderInitializer();
epi.initialize();
assertTrue(epi.getExceptions().size() == 0);
}
}

View file

@ -0,0 +1,15 @@
package org.jivesoftware.smackx;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class WorkgroupProviderInitializerTest {
@Test
public void testWorkgroupProviderInitializer() {
WorkgroupProviderInitializer wpi = new WorkgroupProviderInitializer();
wpi.initialize();
assertTrue(wpi.getExceptions().size() == 0);
}
}

View file

@ -1,16 +0,0 @@
package org.jivesoftware.smackx;
import org.jivesoftware.smack.provider.UrlProviderFileInitializer;
/**
* Loads the default provider file for the Smack extensions on initialization.
*
* @author Robin Collier
*
*/
public class ExtensionInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:META-INF/extension.providers";
}
}

View file

@ -0,0 +1,16 @@
package org.jivesoftware.smackx;
import org.jivesoftware.smack.initializer.UrlProviderFileInitializer;
/**
* Loads the default provider file for the Smack extensions on initialization.
*
* @author Robin Collier
*
*/
public class ExtensionsProviderInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:org.jivesoftware.smackx/extensions.providers";
}
}

View file

@ -0,0 +1,65 @@
package org.jivesoftware.smackx;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.util.FileUtils;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
public class ExtensionsStartupClasses implements SmackInitializer {
private static final String EXTENSIONS_XML = "classpath:org.jivesoftware.smackx/extensions.xml";
private List<Exception> exceptions = new LinkedList<Exception>();
// TODO log
@Override
public void initialize() {
InputStream is;
XmlPullParser parser;
int eventType;
try {
is = FileUtils.getStreamForUrl(EXTENSIONS_XML, null);
parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(is, "UTF-8");
eventType = parser.getEventType();
}
catch (Exception e) {
exceptions.add(e);
return;
}
try {
do {
String name = parser.getName();
if (eventType == XmlPullParser.START_TAG) {
if ("startupClasses".equals(name)) {
try {
SmackConfiguration.parseClassesToLoad(parser, false);
}
catch (Exception e) {
exceptions.add(e);
}
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
is.close();
}
catch (Exception e) {
exceptions.add(e);
}
}
@Override
public List<Exception> getExceptions() {
return Collections.unmodifiableList(exceptions);
}
}

View file

@ -442,4 +442,11 @@
<className>org.jivesoftware.smackx.forward.provider.ForwardedProvider</className>
</extensionProvider>
<!-- Ping (XEP-199) Manager -->
<iqProvider>
<elementName>ping</elementName>
<namespace>urn:xmpp:ping</namespace>
<className>org.jivesoftware.smackx.ping.provider.PingProvider</className>
</iqProvider>
</smackProviders>

View file

@ -0,0 +1,13 @@
<smack>
<startupClasses>
<className>org.jivesoftware.smackx.disco.ServiceDiscoveryManager</className>
<className>org.jivesoftware.smackx.xhtmlim.XHTMLManager</className>
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
<className>org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager</className>
<className>org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager</className>
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
<className>org.jivesoftware.smackx.iqlast.LastActivityManager</className>
<className>org.jivesoftware.smackx.commands.AdHocCommandManager</className>
<className>org.jivesoftware.smackx.ping.PingManager</className>
</startupClasses>
</smack>

View file

@ -0,0 +1,16 @@
package org.jivesoftware.smackx;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ExtensionsProviderInitializerTest {
@Test
public void testExtensionProviderInitializer() {
ExtensionsProviderInitializer ei = new ExtensionsProviderInitializer();
ei.initialize();
assertTrue(ei.getExceptions().size() == 0);
}
}

View file

@ -0,0 +1,16 @@
package org.jivesoftware.smackx;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ExtensionsStartupClassesTest {
@Test
public void testExtensiosnStartupClasses() {
ExtensionsStartupClasses esc = new ExtensionsStartupClasses();
esc.initialize();
assertTrue(esc.getExceptions().size() == 0);
}
}