diff --git a/test/config/test-case.xml b/test/config/test-case.xml
new file mode 100644
index 000000000..0c00bc60d
--- /dev/null
+++ b/test/config/test-case.xml
@@ -0,0 +1,13 @@
+
+
+
+ *
+ * This base class defines a default execution context (i.e. host, port, chat domain and muc
+ * domain) which can be found in the file "config/test-case.xml". However, each subclass could
+ * redefine the default configuration by providing its own configuration file (if desired). The
+ * name of the configuration file must be of the form
+ *
+ * A custom SocketFactory allows fine-grained control of the actual connection to the XMPP
+ * server. A typical use for a custom SocketFactory is when connecting through a SOCKS proxy.
+ *
+ * @return a SocketFactory that will be used to create the socket to the XMPP server.
+ */
+ protected SocketFactory getSocketFactory() {
+ return null;
+ }
+
+ /**
+ * Returns the XMPPConnection located at the requested position. Each test case holds a
+ * pool of connections which is initialized while setting up the test case. The maximum
+ * number of connections is controlled by the message {@link #getMaxConnections()} which
+ * every subclass must implement.
+ *
+ * If the requested position is greater than the connections size then an
+ * IllegalArgumentException will be thrown.
+ *
+ * @param index the position in the pool of the connection to look for.
+ * @return the XMPPConnection located at the requested position.
+ */
+ protected XMPPConnection getConnection(int index) {
+ if (index > getMaxConnections()) {
+ throw new IllegalArgumentException("Index out of bounds");
+ }
+ return connections[index];
+ }
+
+ /**
+ * Returns the name of the user (e.g. johndoe) that is using the connection
+ * located at the requested position.
+ *
+ * @param index the position in the pool of the connection to look for.
+ * @return the user of the user (e.g. johndoe).
+ */
+ protected String getUsername(int index) {
+ if (index > getMaxConnections()) {
+ throw new IllegalArgumentException("Index out of bounds");
+ }
+ return "user" + index;
+ }
+
+ /**
+ * Returns the bare XMPP address of the user (e.g. johndoe@jabber.org) that is
+ * using the connection located at the requested position.
+ *
+ * @param index the position in the pool of the connection to look for.
+ * @return the bare XMPP address of the user (e.g. johndoe@jabber.org).
+ */
+ protected String getBareJID(int index) {
+ return getUsername(index) + "@" + getConnection(index).getHost();
+ }
+
+ /**
+ * Returns the full XMPP address of the user (e.g. johndoe@jabber.org/Smack) that is
+ * using the connection located at the requested position.
+ *
+ * @param index the position in the pool of the connection to look for.
+ * @return the full XMPP address of the user (e.g. johndoe@jabber.org/Smack).
+ */
+ protected String getFullJID(int index) {
+ return getBareJID(index) + "/Smack";
+ }
+
+ protected String getHost() {
+ return host;
+ }
+
+ /**
+ * Returns the default groupchat service domain.
+ *
+ * @return the default groupchat service domain.
+ */
+ protected String getChatDomain() {
+ return chatDomain;
+ }
+
+ /**
+ * Returns the default MUC service domain.
+ *
+ * @return the default MUC service domain.
+ */
+ protected String getMUCDomain() {
+ return mucDomain;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ init();
+ connections = new XMPPConnection[getMaxConnections()];
+ try {
+ // Connect to the server
+ for (int i = 0; i < getMaxConnections(); i++) {
+ if (getSocketFactory() == null) {
+ connections[i] = new XMPPConnection(host, port);
+ }
+ else {
+ connections[i] = new XMPPConnection(host, port, getSocketFactory());
+ }
+ }
+ // Create the test accounts
+ if (!getConnection(0).getAccountManager().supportsAccountCreation())
+ fail("Server does not support account creation");
+
+ for (int i = 0; i < getMaxConnections(); i++) {
+ // Create the test account
+ getConnection(i).getAccountManager().createAccount("user" + i, "user" + i);
+ // Login with the new test account
+ getConnection(i).login("user" + i, "user" + i);
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ for (int i = 0; i < getMaxConnections(); i++) {
+ // Delete the created account for the test
+ getConnection(i).getAccountManager().deleteAccount();
+ // Close the connection
+ getConnection(i).close();
+
+ }
+ }
+
+ /**
+ * Initializes the context of the test case. We will first try to load the configuration from
+ * a file whose name is conformed by the test case class name plus an .xml extension
+ * (e.g RosterTest.xml). If no file was found under that name then we will try to load the
+ * default configuration for all the test cases from the file "config/test-case.xml".
+ *
+ */
+ private void init() {
+ try {
+ boolean found = false;
+ // Try to load the configutation from an XML file specific for this test case
+ Enumeration enum =
+ ClassLoader.getSystemClassLoader().getResources(getConfigurationFilename());
+ while (enum.hasMoreElements()) {
+ found = parseURL((URL) enum.nextElement());
+ }
+ // If none was found then try to load the configuration from the default configuration
+ // file (i.e. "config/test-case.xml")
+ if (!found) {
+ enum = ClassLoader.getSystemClassLoader().getResources("config/test-case.xml");
+ while (enum.hasMoreElements()) {
+ found = parseURL((URL) enum.nextElement());
+ }
+ }
+ if (!found) {
+ System.err.println("File config/test-case.xml not found. Using default config.");
+ }
+ }
+ catch (Exception e) {
+ }
+ }
+
+ /**
+ * Returns true if the given URL was found and parsed without problems. The file provided
+ * by the URL must contain information useful for the test case configuration, such us,
+ * host and port of the server.
+ *
+ * @param url the url of the file to parse.
+ * @return true if the given URL was found and parsed without problems.
+ */
+ private boolean parseURL(URL url) {
+ boolean parsedOK = false;
+ InputStream systemStream = null;
+ try {
+ systemStream = url.openStream();
+ XmlPullParserFactory factory =
+ XmlPullParserFactory.newInstance("org.xmlpull.mxp1.MXParserFactory", null);
+ factory.setNamespaceAware(true);
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(systemStream, "UTF-8");
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("host")) {
+ host = parser.nextText();
+ }
+ else if (parser.getName().equals("port")) {
+ port = parseIntProperty(parser, port);
+ ;
+ }
+ else if (parser.getName().equals("chat")) {
+ chatDomain = parser.nextText();
+ }
+ else if (parser.getName().equals("muc")) {
+ mucDomain = parser.nextText();
+ }
+ }
+ eventType = parser.next();
+ }
+ while (eventType != XmlPullParser.END_DOCUMENT);
+ parsedOK = true;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ try {
+ systemStream.close();
+ }
+ catch (Exception e) {
+ }
+ }
+ return parsedOK;
+ }
+
+ private static int parseIntProperty(XmlPullParser parser, int defaultValue) throws Exception {
+ try {
+ return Integer.parseInt(parser.nextText());
+ }
+ catch (NumberFormatException nfe) {
+ nfe.printStackTrace();
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the name of the configuration file related to this test case. By default all
+ * the test cases will use the same configuration file. However, it's possible to override the
+ * default configuration by providing a file of the form