/***********************************************************
Copyright (C) 2020 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
***********************************************************/
package com.verisign.epp.interfaces.unhandlednamespaces.v1_0;

import java.util.List;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.codec.changepoll.EPPChangeData;
import com.verisign.epp.codec.changepoll.EPPChangePollExtFactory;
import com.verisign.epp.codec.domain.EPPDomainInfoResp;
import com.verisign.epp.codec.domain.EPPDomainMapFactory;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.gen.EPPResult;
import com.verisign.epp.codec.rgpext.EPPRgpExtFactory;
import com.verisign.epp.codec.rgpext.EPPRgpExtInfData;
import com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtInfData;
import com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtFactory;
import com.verisign.epp.codec.unhandlednamespaces.v1_0.EPPUnhandledNamespace;
import com.verisign.epp.interfaces.EPPApplicationSingle;
import com.verisign.epp.interfaces.EPPCommandException;
import com.verisign.epp.interfaces.EPPDomain;
import com.verisign.epp.interfaces.EPPSession;
import com.verisign.epp.interfaces.EPPUnhandledNamespacesLoginAdapter;

import com.verisign.epp.util.Environment;
import com.verisign.epp.util.TestThread;

import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Is a unit test of the com.verisign.epp.codec.domain package with implementing
 * the Unhandled Namespaces {@code RFC 9038}.
 */
public class EPPUnhandledNamespacesTst extends TestCase {

	/**
	 * Handle to the Singleton EPP Application instance
	 * (<code>EPPApplicationSingle</code>)
	 */
	private static EPPApplicationSingle app = EPPApplicationSingle.getInstance();

	/**
	 * Name of configuration file to use for test (default = epp.config).
	 */
	private static String configFileName = "epp.config";

	/**
	 * Logging category
	 */
	private static Logger cat = LoggerFactory.getLogger(EPPUnhandledNamespacesTst.class);
	      

	/**
	 * Current test iteration
	 */
	private int iteration = 0;

	/**
	 * Random instance for the generation of unique objects (hosts, IP addresses,
	 * etc.).
	 */
	private Random rd = new Random(System.currentTimeMillis());

	/**
	 * Allocates an <code>EPPUnhandledNamespacesTst</code> with a logical name.
	 * The constructor will initialize the base class <code>TestCase</code> with
	 * the logical name.
	 *
	 * @param name
	 *           Logical name of the test
	 */
	public EPPUnhandledNamespacesTst(String name) {
		super(name);
	}

	/**
	 * Utility method to clear any messages currently left in the poll queue.
	 */
	public void clearPollQueue() {

		EPPSession theSession = this.createSession();

		try {
			EPPResponse reqResponse = null;

			this.initSession(theSession);

			do {
				theSession.setTransId("ABC-12345");

				theSession.setPollOp(EPPSession.OP_REQ);

				reqResponse = theSession.sendPoll();

				System.out.println("clearPollQueue: Poll Request Response = [" + reqResponse + "]\n\n");

				if (reqResponse.getResult().getCode() == EPPResult.SUCCESS_POLL_MSG) {

					// Poll Ack
					theSession.setPollOp(EPPSession.OP_ACK);

					theSession.setMsgID(reqResponse.getMsgQueue().getId());

					EPPResponse ackResponse = theSession.sendPoll();

					System.out.println("clearPollQueue: Poll Ack Response = [" + ackResponse + "]\n\n");
				}
			}
			while (reqResponse != null && reqResponse.getResult().getCode() == EPPResult.SUCCESS_POLL_MSG);
		}
		catch (EPPCommandException e) {
			handleException(e);
		}

		this.endSession(theSession);

	}

	/**
	 * Test implementing the unhandled namespaces with poll messages created by
	 * the Stub Server. A set of poll messages are created and the test will
	 * consume the poll message with a different set of login services to test
	 * putting the extensions into extValue elements. The steps take in the test
	 * include:<br>
	 * <ol>
	 * <li>Clear poll queue of any existing poll messages.</li>
	 * <li>Create session for sending a domain create command that will result in
	 * poll messages getting created in the server.</li>
	 * <li>Send a domain create command for &quot;un-poll-messages.com&quot; so
	 * that the poll messages needed for the test get created.</li>
	 * <li>Create session with the change poll extension filtered from the login
	 * services.</li>
	 * <li>Send a poll request for the change poll message, which needs to move
	 * the change poll extension to an extValue element.</li>
	 * <li>Create a session with the domain object and the change poll extension
	 * filtered from the login services.</li>
	 * <li>Send a poll request for the change poll message, which needs to move
	 * the domain object and the change poll extension to extValue elements.</li>
	 * <li>Acknowledge the change poll message.</li>
	 * <li>Create a session with the domain object filtered from the login
	 * services.</li>
	 * <li>Send a poll request for the transfer poll message, which needs to move
	 * the domain object to an extValue element.</li>
	 * <li>Acknowledge the transfer poll message.</li>
	 * </ol>
	 */
	public void testPollMessages() {
		printStart("testDomainInfoNoDnssec");

		// Ensure the poll queue is clean
		this.clearPollQueue();

		EPPSession theSession = this.createSession();
		EPPResponse theResponse;

		try {
			this.initSession(theSession);

			EPPDomain theDomain = new EPPDomain(theSession);

			System.out.println("\n----------------------------------------------------------------");

			System.out.println(
			      "testPollMessages: Sending domain create of \"un-poll-messages.com\" to have the server create a set of poll messages for testing.");

			theDomain.setTransId("ABC-12345");
			theDomain.addDomainName("un-poll-messages.com");
			theDomain.setAuthString("2fooBAR");

			theResponse = theDomain.sendCreate();
			System.out.println("Domain create for \"un-poll-messages.com\": Response = [" + theResponse + "]\n\n");

			this.endSession(theSession);

			EPPUnhandledNamespacesLoginAdapter theLoginAdapter;

			// Change poll message with no change poll extension in login services
			System.out
			      .println("Send poll request for change poll message with no change poll extension in login services.");
			theLoginAdapter = new EPPUnhandledNamespacesLoginAdapter();
			theLoginAdapter.addFilterNamespace(EPPChangePollExtFactory.NS);
			theSession = this.createSession();
			theSession.setLoginAdapter(theLoginAdapter);
			this.initSession(theSession);

			// Assert the content of the poll message
			theSession.setTransId("NO-CHANGEPOLL-1");
			theSession.setPollOp(EPPSession.OP_REQ);
			theResponse = theSession.sendPoll();
			System.out.println("testPollMessages: Poll Response = [" + theResponse + "]\n\n");

			// Assert the content of the poll message
			Assert.assertEquals(EPPResult.SUCCESS_POLL_MSG, theResponse.getResult().getCode());
			Assert.assertEquals(EPPDomainInfoResp.class.getName(), theResponse.getClass().getName());
			Assert.assertFalse("Response must not have change poll extension",
			      theResponse.hasExtension(EPPChangeData.class));
			List<EPPUnhandledNamespace> theUnhandledNamespaces = EPPUnhandledNamespace.fromResponse(theResponse);
			Assert.assertNotNull("Response must include unhandled namespace element", theUnhandledNamespaces);
			Assert.assertEquals(1, theUnhandledNamespaces.size());
			Assert.assertEquals(EPPChangePollExtFactory.NS, theUnhandledNamespaces.get(0).getNamespaceUri());
			EPPUnhandledNamespace.printUnhandledNamespaces(theUnhandledNamespaces);

			this.endSession(theSession);

			// Change poll message with no change poll extension and no domain
			// object in the login services
			System.out.println(
			      "Send poll request for change poll message with no domain object and change poll extension in login services.");
			theLoginAdapter = new EPPUnhandledNamespacesLoginAdapter();
			theLoginAdapter.addFilterNamespace(EPPDomainMapFactory.NS);
			theLoginAdapter.addFilterNamespace(EPPChangePollExtFactory.NS);
			theSession = this.createSession();
			theSession.setLoginAdapter(theLoginAdapter);
			this.initSession(theSession);

			// Assert the content of the poll message
			theSession.setTransId("NO-DOMAIN-CHANGEPOLL-1");
			theSession.setPollOp(EPPSession.OP_REQ);
			theResponse = theSession.sendPoll();
			System.out.println("testPollMessages: Poll Response = [" + theResponse + "]\n\n");

			// Assert the content of the poll message
			Assert.assertEquals(EPPResult.SUCCESS_POLL_MSG, theResponse.getResult().getCode());
			Assert.assertEquals(EPPResponse.class.getName(), theResponse.getClass().getName());
			Assert.assertFalse("Response must not have change poll extension",
			      theResponse.hasExtension(EPPChangeData.class));
			theUnhandledNamespaces = EPPUnhandledNamespace.fromResponse(theResponse);
			Assert.assertNotNull("Response must include unhandled namespace elements", theUnhandledNamespaces);
			Assert.assertEquals(2, theUnhandledNamespaces.size());
			Assert.assertEquals(EPPDomainMapFactory.NS, theUnhandledNamespaces.get(0).getNamespaceUri());
			Assert.assertEquals(EPPChangePollExtFactory.NS, theUnhandledNamespaces.get(1).getNamespaceUri());
			EPPUnhandledNamespace.printUnhandledNamespaces(theUnhandledNamespaces);

			// Acknowledge the change poll message
			theSession.setTransId("NO-DOMAIN-CHANGEPOLL-ACK-1");
			theSession.setPollOp(EPPSession.OP_ACK);
			theSession.setMsgID(theResponse.getMsgQueue().getId());
			theResponse = theSession.sendPoll();
			System.out.println("testPollMessages: Poll Ack Response = [" + theResponse + "]\n\n");

			this.endSession(theSession);

			// Transfer poll message with no domain object in the login services
			System.out.println("Send poll request for transfer poll message with no domain object in login services.");
			theLoginAdapter = new EPPUnhandledNamespacesLoginAdapter();
			theLoginAdapter.addFilterNamespace(EPPDomainMapFactory.NS);
			theSession = this.createSession();
			theSession.setLoginAdapter(theLoginAdapter);
			this.initSession(theSession);

			// Assert the content of the poll message
			theSession.setTransId("NO-DOMAIN-1");
			theSession.setPollOp(EPPSession.OP_REQ);
			theResponse = theSession.sendPoll();
			System.out.println("testPollMessages: Poll Response = [" + theResponse + "]\n\n");

			// Assert the content of the poll message
			Assert.assertEquals(EPPResult.SUCCESS_POLL_MSG, theResponse.getResult().getCode());
			Assert.assertEquals(EPPResponse.class.getName(), theResponse.getClass().getName());

			theUnhandledNamespaces = EPPUnhandledNamespace.fromResponse(theResponse);
			Assert.assertNotNull("Response must include unhandled namespace elements", theUnhandledNamespaces);
			Assert.assertEquals(1, theUnhandledNamespaces.size());
			Assert.assertEquals(EPPDomainMapFactory.NS, theUnhandledNamespaces.get(0).getNamespaceUri());
			EPPUnhandledNamespace.printUnhandledNamespaces(theUnhandledNamespaces);

			// Acknowledge the change poll message
			theSession.setTransId("NO-DOMAIN-ACK-1");
			theSession.setPollOp(EPPSession.OP_ACK);
			theSession.setMsgID(theResponse.getMsgQueue().getId());
			theResponse = theSession.sendPoll();
			System.out.println("testPollMessages: Poll Ack Response = [" + theResponse + "]\n\n");

			this.endSession(theSession);
		}
		catch (EPPCommandException e) {
			handleException(e);
		}

		printEnd("testDomainInfoNoDnssec");
	}

	/**
	 * Test establishing a session without the DNSSEC extension and send the
	 * domain info command for a DNSSEC enabled domain. The steps take in the
	 * test include:<br>
	 * <ol>
	 * <li>Create a new session that filters the DNSSEC extension from the login
	 * services.</li>
	 * <li>Send an domain info command for &quot;un-no-dnssec.com&quot;, which
	 * should return a response that has DNSSEC data.</li>
	 * <li>Assert that the response does not include the DNSSEC extension and
	 * that the DNSSEC extension is set in an extValue element.</li>
	 * <li>End the session</li>
	 * </ol>
	 */
	public void testDomainInfoNoDnssec() {
		printStart("testDomainInfoNoDnssec");

		EPPResponse theResponse;
		EPPSession theSession = this.createSession();

		try {
			theSession.setLoginAdapter(new EPPUnhandledNamespacesLoginAdapter(EPPSecDNSExtFactory.NS));
			this.initSession(theSession);

			EPPDomain theDomain = new EPPDomain(theSession);

			System.out.println("\n----------------------------------------------------------------");

			System.out.println(
			      "testDomainInfoNoDnssec: Sending domain info command with session without DNSSEC extension in login services");

			theDomain.setTransId("ABC-12345");

			theDomain.addDomainName("un-no-dnssec.com");

			theResponse = theDomain.sendInfo();

			// -- Output all of the response attributes
			System.out.println("testDomainInfoNoDnssec: Info Response = [" + theResponse + "]\n\n");

			Assert.assertFalse("Response must not have DNSSEC extension",
			      theResponse.hasExtension(EPPSecDNSExtInfData.class));

			List<EPPUnhandledNamespace> theUnhandledNamespaces = EPPUnhandledNamespace.fromResponse(theResponse);
			Assert.assertNotNull("Response must include unhandled namespace element", theUnhandledNamespaces);
			Assert.assertEquals(1, theUnhandledNamespaces.size());
			Assert.assertEquals(EPPSecDNSExtFactory.NS, theUnhandledNamespaces.get(0).getNamespaceUri());
			EPPUnhandledNamespace.printUnhandledNamespaces(theUnhandledNamespaces);
		}
		catch (EPPCommandException e) {
			handleException(e);
		}

		this.endSession(theSession);

		printEnd("testDomainInfoNoDnssec");
	}

	/**
	 * Test establishing a session without the RGP extension and send the domain
	 * info command for a domain in RGP. The steps take in the test include:<br>
	 * <ol>
	 * <li>Create a new session that filters the RGP extension from the login
	 * services.</li>
	 * <li>Send an domain info command for &quot;un-no-rgp.com&quot;, which
	 * should return a response that has RGP data.</li>
	 * <li>Assert that the response does not include the RGP extension and that
	 * the RGP extension is set in an extValue element.</li>
	 * <li>End the session</li>
	 * </ol>
	 */
	public void testDomainInfoNoRgp() {
		printStart("testDomainInfoNoRgp");

		EPPResponse theResponse;
		EPPSession theSession = this.createSession();

		try {
			theSession.setLoginAdapter(new EPPUnhandledNamespacesLoginAdapter(EPPRgpExtFactory.NS));
			this.initSession(theSession);

			EPPDomain theDomain = new EPPDomain(theSession);

			System.out.println("\n----------------------------------------------------------------");

			System.out.println(
			      "testDomainInfoNoRgp: Sending domain info command with session without RGP extension in login services");

			theDomain.setTransId("ABC-12345");

			theDomain.addDomainName("un-no-rgp.com");

			theResponse = theDomain.sendInfo();

			// -- Output all of the response attributes
			System.out.println("testDomainInfoNoDnssec: Info Response = [" + theResponse + "]\n\n");

			Assert.assertFalse("Response must not have RGP extension", theResponse.hasExtension(EPPRgpExtInfData.class));

			List<EPPUnhandledNamespace> theUnhandledNamespaces = EPPUnhandledNamespace.fromResponse(theResponse);
			Assert.assertNotNull("Response must include unhandled namespace element", theUnhandledNamespaces);
			Assert.assertEquals(1, theUnhandledNamespaces.size());
			Assert.assertEquals(EPPRgpExtFactory.NS, theUnhandledNamespaces.get(0).getNamespaceUri());
			EPPUnhandledNamespace.printUnhandledNamespaces(theUnhandledNamespaces);
		}
		catch (EPPCommandException e) {
			handleException(e);
		}

		this.endSession(theSession);

		printEnd("testDomainInfoNoRgp");
	}

	/**
	 * Unit test of <code>EPPSession.initSession</code>. The session attribute is
	 * initialized with the attributes defined in the EPP sample files. This will
	 * send the login command to the server.
	 *
	 * @param aSession
	 *           Session to initialize.
	 */
	private void initSession(EPPSession aSession) {
		printStart("initSession");

		// Set attributes for initSession
		aSession.setTransId("ABC-12345-XYZ");

		aSession.setVersion("1.0");

		aSession.setLang("en");

		// Initialize the session
		try {
			aSession.initSession();
		}

		catch (EPPCommandException e) {
			EPPResponse response = aSession.getResponse();

			// Is a server specified error?
			if ((response != null) && (!response.isSuccess())) {
				Assert.fail("Server Error : " + response);
			}
			else {
				e.printStackTrace();

				Assert.fail("initSession Error : " + e);
			}
		}

		printEnd("initSession");
	}

	// End EPPUnhandledNamespacesTst.initSession()

	/**
	 * Unit test of <code>EPPSession.endSession</code>. The session with the EPP
	 * Server will be terminated.
	 *
	 * @param aSession
	 *           Session to end
	 */
	private void endSession(EPPSession aSession) {
		printStart("endSession");

		aSession.setTransId("ABC-12345-XYZ");

		// End the session
		try {
			aSession.endSession();
		}

		catch (EPPCommandException e) {
			EPPResponse response = aSession.getResponse();

			// Is a server specified error?
			if ((response != null) && (!response.isSuccess())) {
				Assert.fail("Server Error : " + response);
			}

			else // Other error
			{
				e.printStackTrace();

				Assert.fail("initSession Error : " + e);
			}
		}

		printEnd("endSession");
	}

	/**
	 * Creates an {@link EPPSession} with the default settings. The
	 * {@link EPPSession} is not initialize via the login command.
	 *
	 * @return Instance of an {@link EPPSession}
	 */
	private EPPSession createSession() {
		EPPSession theSession = null;

		try {
			String theSessionClassName = System.getProperty("EPP.SessionClass");

			if (theSessionClassName != null) {
				try {
					Class theSessionClass = Class.forName(theSessionClassName);

					if (!EPPSession.class.isAssignableFrom((theSessionClass))) {
						Assert.fail(theSessionClassName + " is not a subclass of EPPSession");
					}

					theSession = (EPPSession) theSessionClass.getDeclaredConstructor().newInstance();
				}
				catch (Exception ex) {
					Assert.fail("Exception instantiating EPP.SessionClass value " + theSessionClassName + ": " + ex);
				}
			}
			else {
				theSession = new EPPSession();
			}

			theSession.setClientID(Environment.getProperty("EPP.Test.clientId", "ClientX"));
			theSession.setPassword(Environment.getProperty("EPP.Test.password", "foo-BAR2"));
			theSession.setTransId("ABC-12345-XYZ");
			theSession.setVersion("1.0");
			theSession.setLang("en");
		}

		catch (Exception e) {
			e.printStackTrace();

			Assert.fail("Error initializing the session: " + e);
		}

		return theSession;
	}

	// End EPPUnhandledNamespacesTst.endSession()

	/**
	 * JUNIT <code>setUp</code> method, which sets the default client Id to
	 * "theRegistrar".
	 */
	@Override
	protected void setUp() {
	}

	/**
	 * JUNIT <code>tearDown</code>, which currently does nothing.
	 */
	@Override
	protected void tearDown() {
	}

	/**
	 * JUNIT <code>suite</code> static method, which returns the tests associated
	 * with <code>EPPUnhandledNamespacesTst</code>.
	 *
	 * @return Test suite
	 */
	public static Test suite() {
		TestSuite suite = new TestSuite(EPPUnhandledNamespacesTst.class);

		String theConfigFileName = System.getProperty("EPP.ConfigFile");
		if (theConfigFileName != null) {
			configFileName = theConfigFileName;
		}

		try {
			app.initialize(configFileName);
		}
		catch (EPPCommandException e) {
			e.printStackTrace();

			Assert.fail("Error initializing the EPP Application: " + e);
		}

		return suite;
	}

	/**
	 * Handle an <code>EPPCommandException</code>, which can be either a server
	 * generated error or a general exception. If the exception was caused by a
	 * server error, "Server Error :&lt;Response XML&gt;" will be specified. If
	 * the exception was caused by a general algorithm error, "General Error
	 * :&lt;Exception Description&gt;" will be specified.
	 *
	 * @param aException
	 *           Exception thrown during test
	 */
	public void handleException(Exception aException) {
		EPPResponse theResponse = null;
		if (aException instanceof EPPCommandException) {
			theResponse = ((EPPCommandException) aException).getResponse();
		}

		aException.printStackTrace();

		// Is a server specified error?
		if ((theResponse != null) && (!theResponse.isSuccess())) {
			Assert.fail("Server Error : " + theResponse);
		}

		else {
			Assert.fail("General Error : " + aException);
		}
	}

	/**
	 * Unit test main, which accepts the following system property options: <br>
	 *
	 * <ul>
	 * <li>iterations Number of unit test iterations to run</li>
	 * <li>validate Turn XML validation on (<code>true</code>) or off
	 * (<code>false</code>). If validate is not specified, validation will be
	 * off.</li>
	 * </ul>
	 *
	 *
	 * @param args
	 *           DOCUMENT ME!
	 */
	public static void main(String[] args) {
		// Override the default configuration file name?
		if (args.length > 0) {
			configFileName = args[0];
		}

		// Number of Threads
		int numThreads = 1;

		String threadsStr = System.getProperty("threads");

		if (threadsStr != null) {
			numThreads = Integer.parseInt(threadsStr);

			// Run test suite in multiple threads?
		}

		if (numThreads > 1) {
			// Spawn each thread passing in the Test Suite
			for (int i = 0; i < numThreads; i++) {
				TestThread thread = new TestThread("EPPSessionTst Thread " + i, EPPUnhandledNamespacesTst.suite());

				thread.start();
			}
		}

		else { // Single threaded mode.
			junit.textui.TestRunner.run(EPPUnhandledNamespacesTst.suite());
		}

		try {
			app.endApplication();
		}

		catch (EPPCommandException e) {
			e.printStackTrace();

			Assert.fail("Error ending the EPP Application: " + e);
		}
	}

	/**
	 * This method tries to generate a unique String as Domain Name and Name
	 * Server
	 *
	 * @return A unique domain name
	 */
	public String makeDomainName() {
		long tm = System.currentTimeMillis();

		return new String("EPPUnhandledNamespacesTst" + Thread.currentThread()
		      + String.valueOf(tm + this.rd.nextInt(12)).substring(10) + ".com");
	}

	/**
	 * Makes a unique IP address based off of the current time.
	 *
	 * @return Unique IP address <code>String</code>
	 */
	public String makeIP() {
		long tm = System.currentTimeMillis();

		return new String(String.valueOf(tm + this.rd.nextInt(50)).substring(10) + "."
		      + String.valueOf(tm + this.rd.nextInt(50)).substring(10) + "."
		      + String.valueOf(tm + this.rd.nextInt(50)).substring(10) + "."
		      + String.valueOf(tm + this.rd.nextInt(50)).substring(10));
	}

	/**
	 * Makes a unique host name for a domain using the current time.
	 *
	 * @param aDomainName
	 *           Domain name
	 *
	 * @return Unique host name <code>String</code>
	 */
	public String makeHostName(String aDomainName) {
		long tm = System.currentTimeMillis();

		return new String(String.valueOf(tm + this.rd.nextInt(10)).substring(10) + "." + aDomainName);
	}

	/**
	 * Makes a unique contact name using the current time.
	 *
	 * @return Unique contact name <code>String</code>
	 */
	public String makeContactName() {
		long tm = System.currentTimeMillis();

		return new String("SAI" + String.valueOf(tm + this.rd.nextInt(5)).substring(7));
	}

	/**
	 * Print the start of a test with the <code>Thread</code> name if the current
	 * thread is a <code>TestThread</code>.
	 *
	 * @param aTest
	 *           name for the test
	 */
	private void printStart(String aTest) {
		if (Thread.currentThread() instanceof TestThread) {
			System.out.print(Thread.currentThread().getName() + ", iteration " + this.iteration + ": ");

			cat.info(Thread.currentThread().getName() + ", iteration " + this.iteration + ": " + aTest + " Start");
		}

		System.out.println("Start of " + aTest);

		System.out.println("****************************************************************\n");
	}

	/**
	 * Print the end of a test with the <code>Thread</code> name if the current
	 * thread is a <code>TestThread</code>.
	 *
	 * @param aTest
	 *           name for the test
	 */
	private void printEnd(String aTest) {
		System.out.println("****************************************************************");

		if (Thread.currentThread() instanceof TestThread) {
			System.out.print(Thread.currentThread().getName() + ", iteration " + this.iteration + ": ");

			cat.info(Thread.currentThread().getName() + ", iteration " + this.iteration + ": " + aTest + " End");
		}

		System.out.println("End of " + aTest);

		System.out.println("\n");
	}

}

// End class EPPUnhandledNamespacesTst
