[embjopr-commits] EMBJOPR SVN: r171 - in trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit: as5 and 1 other directory.

embjopr-commits at lists.jboss.org embjopr-commits at lists.jboss.org
Fri Feb 27 01:51:59 EST 2009


Author: ozizka at redhat.com
Date: 2009-02-27 01:51:59 -0500 (Fri, 27 Feb 2009)
New Revision: 171

Modified:
   trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/AppConstants.java
   trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/ApplicationTestBaseAS5.java
   trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/EarTest.java
Log:
Several EAR tests added.

Modified: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/AppConstants.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/AppConstants.java	2009-02-27 02:04:19 UTC (rev 170)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/AppConstants.java	2009-02-27 06:51:59 UTC (rev 171)
@@ -23,6 +23,34 @@
 package org.jboss.jopr.jsfunit;
 
 public interface AppConstants {
+
+		public static final String SYSPROP_DEPLOY_DIR = "jsfunit.deploy.dir";
+		public static final String SYSPROP_TESTDATA_DIR = "jsfunit.testdata";
+
+
+		public enum DeployableTypes {
+
+			EAR(AppConstants.NAV_EAR),
+			WAR(AppConstants.NAV_WAR),
+			EJB(AppConstants.NAV_EJB),
+			SAR(AppConstants.NAV_SAR),
+			RAR(AppConstants.NAV_RAR),
+			MC_BEAN(AppConstants.NAV_MC);
+
+			protected final String navTreeLabel;
+			public String getNavTreeLabel() {			return navTreeLabel;		}
+
+			DeployableTypes( String navTreeLabel ){
+				this.navTreeLabel = navTreeLabel;
+			}
+
+		}
+
+		public enum DeploymentMeans {
+			VIA_EMBJOPR,
+			VIA_FILESYSTEM,
+			VIA_JMX
+		}
     
     // Navigation
     public static final String NAV_EJB = "EJB Application (EJB JAR)s";
@@ -38,13 +66,19 @@
     // Test Archives
     public static final String BASIC_JAR = "deployment-ejb.jar";
     public static final String BASIC_EAR = "eardeployment.ear";
+		public static final String EAR_UNPACKED = "unpacked-ear1.ear";
+		public static final String EAR_UNPACKED_ZIP = "unpacked-ear1.ear.zip";
     public static final String BASIC_WAR = "hellothere.war";
 
     // Defaults
-    public static final String[] WAR_DEFAULTS = new String[]{"ROOT.war", "invoker.war",
+    public static final String[] WAR_DEFAULTS = new String[]{
+			"ROOT.war", "invoker.war",
 			"jbas5-admin-console.war", "jbossws-management.war",
-                        "jmx-console.war", "web-console.war"};
-    public static final String[] SAR_DEFAULTS = new String[]{"cache-invalidation-service.xml",
+      "jmx-console.war", "web-console.war"
+		};
+
+    public static final String[] SAR_DEFAULTS = new String[]{
+			"cache-invalidation-service.xml",
 			"connection-factories-service.xml", "console-mgr.sar",
 			"destinations-service.xml", "ejb2-timer-service.xml",
 			"hsqldb-ds.xml", "hsqldb-persistence-service.xml",
@@ -54,5 +88,7 @@
 			"mail-service.xml", "messaging-service.xml", "monitoring-service.xml",
 			"properties-service.xml", "remoting-bisocket-service.xml",
 			"schedule-manager-service.xml", "scheduler-service.xml",
-			"sqlexception-service.xml", "transaction-service.xml", "uuid-key-generator.sar"};
+			"sqlexception-service.xml", "transaction-service.xml", "uuid-key-generator.sar"
+		};
+		
 }

Modified: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/ApplicationTestBaseAS5.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/ApplicationTestBaseAS5.java	2009-02-27 02:04:19 UTC (rev 170)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/ApplicationTestBaseAS5.java	2009-02-27 06:51:59 UTC (rev 171)
@@ -35,6 +35,9 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
+import org.apache.commons.lang.StringUtils;
+import org.w3c.dom.Element;
 
 
 
@@ -47,13 +50,16 @@
 public abstract class ApplicationTestBaseAS5 extends EmbjoprTestCase
 				implements AppConstants {
 
-	//protected String label = null;
-	//protected final String serviceName = null;
-	//protected final String xmlElementName = null;
-	//protected final String templateHtmlSelectValue = null;
 
+	public ApplicationTestBaseAS5() {
+		super();
+	}
 
+	public ApplicationTestBaseAS5(String theName) {
+		//super(theName);
+	}
 
+
 	public HtmlButtonInput getAppDeleteButton(String resourceName)
 	{
 		return getDeleteButton("resourceSummaryForm", resourceName);
@@ -155,9 +161,6 @@
 	}
 
 
-	public void announceCurrentTest(){
-		log.info( " --------  Test: "+DebugUtils.getCurrentMethodFullName()+"  -------- ");
-	}
 
 
 
@@ -232,7 +235,10 @@
 
 			// A table which has an anchor containing given text.
 			// Note: Different node types have different id endings - typeSummaryLink, categorySummaryLink, ...
-			String xPath = ".//table[.//td[contains(@id,':text')]//a[contains(@id,'SummaryLink') and normalize-space() = '"+label+"']]";
+			//String xPath = ".//table[.//td[contains(@id,':text')]//a[contains(@id,'SummaryLink') and normalize-space() = '"+label+"']]";
+			// Node has @id = navTreeForm:navTree:136:137:138:139:143:195::instanceNodeOrLeafLink
+			// Let's rely on the ":text" id part only and suppose there will be just one link in that TD.
+			String xPath = ".//table[.//td[contains(@id,':text')]//a[normalize-space() = '"+label+"']]";
 
 			HtmlTable nodeTable = navTreeForm.getFirstByXPath( xPath );
 
@@ -446,7 +452,7 @@
 	/**
 	 * Inner class for manipulation with tab content box.
 	 */
-	protected class TabContentBox extends PageContextAwareElement {
+	protected class TabContentBox extends PageAware {
 
 		private HtmlElement element;
 		public HtmlElement getElement() {			return element;		}
@@ -500,18 +506,50 @@
 	
 
 	/**
-	 * Row of a content table.
 	 * Contains convenience methods for accessing content tables in EmbJopr.
 	 */
 	protected class ContentTable {
 
+		public static final String ID_CATEGORY_DATA_TABLE = "categorySummaryForm:dataTable";
+		public static final String ID_RESOURCE_DATA_TABLE = "resourceSummaryForm:dataTable";
+
 		private HtmlTable element;
 		public HtmlTable getElement() {			return element;		}
 
-		public ContentTable( HtmlTable element) {
+		/**
+		 * Creates a data table wrapper for the given table element.
+		 */
+		public ContentTable( HtmlTable element ) {
 			this.element = element;
 		}
 
+		/**
+		 * Creates a data table wrapper for first found element with one of these IDs:
+		 * ID_CATEGORY_DATA_TABLE, ID_RESOURCE_DATA_TABLE
+		 *
+		 * This method assumes there's only one "data table" per page.
+		 * If not, it simply returns the first in the order of IDs searched.
+		 * You can always specify the element using ContentTable( HtmlTable element ).
+		 */
+		public ContentTable() throws HtmlElementNotFoundException {
+
+			// Find the data table - try some known IDs.
+			String[] elemIDs = { ID_CATEGORY_DATA_TABLE, ID_RESOURCE_DATA_TABLE };
+			Element elem = null;
+			for( String elemID : elemIDs ){
+				elem = client.getElement(elemID);
+				if( null != elem )
+					break;
+			}
+			if( null == elem )
+				throw new HtmlElementNotFoundException(
+								"Can't find the content table element, searched IDs: "
+								+ elemIDs.toString() );
+
+			this.element = (HtmlTable)elem;
+		}
+
+
 		// Columns maps 
 		private List<String> colLabels = null;
 		private Map<String, Integer> colIndexes = null;
@@ -541,16 +579,40 @@
 			return new ContentTableRow(elm, this);
 		}
 
+
+
+		/**
+		 * Returns wrapper of the table row which contains a link with given label,
+		 * or null when the no such row is found.
+		 */
+		public ContentTableRow findFirstRowContainingLink( String linkLabel )
+		{
+			if( 0 == element.getRowCount() )
+				return null;
+
+			String xPath = ".//tr[.//a[normalize-space()='"+linkLabel+"']]";
+			HtmlTableRow elm = (HtmlTableRow) element.getFirstByXPath(xPath);
+			if( null == elm )
+				return null;
+			return new ContentTableRow(elm, this);
+		}
+
+		/**
+		 * Returns wrapper of the table row which contains a link with given label.
+		 * @throws org.jboss.jopr.jsfunit.exceptions.HtmlElementNotFoundException
+		 *				 when no row with such label found.
+		 */
 		public ContentTableRow getFirstRowContainingLink( String linkLabel ) 
 						throws HtmlElementNotFoundException
 		{
 			if( 0 == element.getRowCount() )
 				throw new HtmlElementNotFoundException("Table has no rows.");
 
-			String xPath = ".//tr[//a[normalize-space()='"+linkLabel+"']]";
+			String xPath = ".//tr[.//a[normalize-space()='"+linkLabel+"']]";
 			HtmlTableRow elm = (HtmlTableRow) element.getFirstByXPath(xPath);
 			if( null == elm )
-				throw new HtmlElementNotFoundException(xPath);
+				throw new HtmlElementNotFoundException(
+								"Can't find row containing link '"+linkLabel+"' using XPath: "+xPath);
 			return new ContentTableRow(elm, this);
 		}
 
@@ -615,7 +677,40 @@
 
 
 
+
+
 	/**
+	 * Provides extra method that parses text-like info table (with one column).
+	 */
+	protected class ContentInfoTable extends ContentTable {
+
+		public ContentInfoTable(HtmlTable element) {
+			super(element);
+		}
+
+		/**
+		 * Parses the content of the table for properties.
+		 * @return
+		 */
+		public Properties getProperties()
+		{
+			Properties props = new Properties();
+
+			// The template has label in span/strong and the value as text in td.
+			String xPath = ".//tr/td[span/strong]";
+			List<HtmlTableCell> cells  = (List<HtmlTableCell>) this.getElement().getByXPath(xPath);
+			for( HtmlTableCell cell : cells ){
+				String[] parts = cell.getTextContent().split(":");
+				props.put(parts[0], parts[1]);
+			}
+			return props;
+		}
+
+	}// inner class ContentInfoTable
+
+
+
+	/**
 	 * Row of a content table.
 	 * Contains convenience methods for accessing content table rows in EmbJopr.
 	 */
@@ -681,8 +776,16 @@
 		public HtmlAnchor getLinkByLabel(String linkLabel) throws HtmlElementNotFoundException {
 			String xPath = ".//a[normalize-space()='"+linkLabel+"']";
 			HtmlAnchor link = (HtmlAnchor) this.element.getFirstByXPath(xPath);
-			if( null == link )
-				throw new HtmlElementNotFoundException(xPath);
+			if( null == link ){
+				StringBuilder sb = new StringBuilder();
+				List<HtmlElement> linksFound = this.element.getHtmlElementsByTagName("a");
+				for( HtmlElement linkFound : linksFound ){
+					sb.append("'").append( ((HtmlAnchor)linkFound).getTextContent() ).append("', ");
+				}
+				String availLinks = StringUtils.removeEnd( sb.toString(), ", " );
+
+				throw new HtmlElementNotFoundException("Can't find link using '"+xPath+"', available: "+availLinks);
+			}
 			return link;
 		}
 
@@ -724,6 +827,7 @@
 
 	/**
 	 *  Pagination control
+	 *  Not tested yet.
 	 */
 	protected class ContentBoxPagination {
 
@@ -796,6 +900,7 @@
 				pageSizeSelect.getOptionByValue(optionValue);
 			}
 			catch( ElementNotFoundException ex ){
+				// Print out available options.
 				StringBuilder sb = new StringBuilder(pageSizeSelect.getOptionSize());
 				for( HtmlOption opt : pageSizeSelect.getOptions() ){
 					sb.append(" ").append(opt.getValueAttribute());
@@ -808,10 +913,46 @@
 			pageSizeSelect.setSelectedAttribute(optionValue, true);
 		}
 
+	}// ContentBoxPagination
+
+
+
+
+
+
+	// TODO
+	protected class JMXDeploymentInfo {
+
+		// Etc...
+		public boolean isDeployed(){
+			return false;
+		}
+
 	}
 
+	// TODO
+	protected class FileDeploymentInfo {
 
+		// Etc...
+		public boolean isDeployed(){
+			return false;
+		}
 
+	}
+
+	// TODO
+	protected class EmbJoprDeploymentInfo {
+
+		// Etc...
+		public boolean isDeployed(){
+			return false;
+		}
+
+	}
+
+
+
+
 }// ApplicationTestBaseAS5 
 
 

Modified: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/EarTest.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/EarTest.java	2009-02-27 02:04:19 UTC (rev 170)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/EarTest.java	2009-02-27 06:51:59 UTC (rev 171)
@@ -22,11 +22,29 @@
 
 package org.jboss.jopr.jsfunit.as5;
 
+import java.io.FileNotFoundException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
 import org.jboss.jopr.jsfunit.*;
 import com.gargoylesoftware.htmlunit.html.*;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipInputStream;
+import javax.faces.application.FacesMessage;
+import javax.faces.application.FacesMessage.Severity;
 import junit.framework.Test;
+import junit.framework.TestCase;
 import junit.framework.TestSuite;
+import org.apache.commons.lang.StringUtils;
+import org.jboss.jopr.jsfunit.AppConstants.DeployableTypes;
 import org.jboss.jopr.jsfunit.exceptions.ActionNotAvailableException;
 import org.jboss.jopr.jsfunit.exceptions.ActionOutOfSyncException;
 import org.jboss.jopr.jsfunit.exceptions.EmbJoprTestException;
@@ -50,10 +68,29 @@
 
 	public static Test suite()
 	{
-		return new TestSuite(EarTest.class);
+		String testToRun = System.getProperty("jsfunit.test.single");
+		if( null == testToRun ){
+			return new TestSuite(EarTest.class);
+		}
+		else{
+			// TODO: Try running single test set in system property.
+			// http://members.pingnet.ch/gamma/junit.htm
+			TestSuite suite = new TestSuite();
+			//suite.addTest(this.getClass().getConstructor(String.class).newInstance(testToRun));
+			suite.addTest( new EarTest(testToRun) );
+			return suite;
+		}
 	}
 
+	public EarTest() {
+	}
+	private EarTest(String testToRun) {
+		super(testToRun);
+	}
 
+
+
+
 	/*
 	 * testName: testBasicEarDeployment
    * assertion:  verify basic deployment of Enterprise Archive
@@ -61,23 +98,25 @@
 	 *	Add a new resource.  Verify the resource was successfully
 	 *	deployed.  Undeploy the archive for test clean up purposes.
 	 *
+	 * FAILED: JMX doesn't report EAR as deployed: eardeployment.ear
 	 */ 
 	public void testBasicEarDeployment() throws IOException, EmbJoprTestException
 	{
 
-		String earFilePath = System.getProperty("jsfunit.testdata") + "/ear/"+BASIC_EAR;
+		// Deploy the EAR.
+		String earFilePath = System.getProperty(SYSPROP_TESTDATA_DIR) + "/ear/"+BASIC_EAR;
 		deployEar( earFilePath );
 
 		String expectedMessage = BASIC_EAR + " created successfully";
 
 		checkClientAndServerMessages(expectedMessage, expectedMessage, false);
 
-		// Use JMX to assert that the EAR components really did deploy successfully
-		assertTrue("JMX doesn't report EAR as exposed: eardeployment.ear", isEarDeployed(BASIC_EAR));
-		assertTrue("JMX doesn't report EJB sessiona.jar as exposed.", isEJBDeployed("sessiona.jar"));
-		assertTrue("JMX doesn't report EJB sessionb.jar as exposed.", isEJBDeployed("sessionb.jar"));
+		// Use JMX to assert that the EAR components really did deploy successfully.
+		assertTrue("JMX doesn't report EAR as deployed: eardeployment.ear", isEarDeployed(BASIC_EAR));
+		assertTrue("JMX doesn't report EJB sessiona.jar as deployed.", isEJBDeployed("sessiona.jar"));
+		assertTrue("JMX doesn't report EJB sessionb.jar as deployed.", isEJBDeployed("sessionb.jar"));
 
-		// Undeploy the EAR
+		// Undeploy the EAR.
 		undeployEar( BASIC_EAR );
 
 		expectedMessage = "Successfully deleted Enterprise Application (EAR) '"+BASIC_EAR+"'.";
@@ -106,9 +145,9 @@
 				verify the archive has been deployed successfully.
 	 
 	 */
-	public void testBadEarRedeploy() throws IOException {
+	public void DISABLEDtestBadEarRedeploy() throws IOException {
 
-		String earFilePath = System.getProperty("jsfunit.testdata") + "/ear/"+EAR_MALFORMED_APP_FILENAME;
+		String earFilePath = System.getProperty(SYSPROP_TESTDATA_DIR) + "/ear/"+EAR_MALFORMED_APP_FILENAME;
 		deployEar(earFilePath);
 
 		checkClientAndServerMessages("Failed to create Resource", "Failed to create Resource", true);
@@ -116,6 +155,8 @@
 	}
 
 
+
+
 	/**
 	 * assertion:
 	  
@@ -126,17 +167,15 @@
 	    From the root of the navigation tree:
 			Click JBossAS Servers ==> JBoss App Server:${config}
 	          ==> Applications ==> Enterprise Application
-	  
-	 * @param earFilePath
-	 * @throws java.io.IOException
+
+	 *  PASSED.
 	 */
-	public void testNavigationToEar() throws IOException, HtmlElementNotFoundException, ActionOutOfSyncException, ActionNotAvailableException
+	public void testNavigationToEar() throws IOException, HtmlElementNotFoundException, ActionOutOfSyncException, ActionNotAvailableException, EmbJoprTestException, InterruptedException
 	{
-		announceCurrentTest();
 
+		// JBossAS Servers node 
 		NavTreeNode nodeServers = navTree.getNodeByLabel("JBossAS Servers");
 		nodeServers.click();
-		// --- click ---
 
 		{
 			String headerText = "JBossAS Server";
@@ -159,8 +198,8 @@
 
 			((HtmlAnchor)firstLink).click();
 		}
-		// --- click ---
 
+		// JBoss App Server:${config} node
 		{
 			String pageText = client.getPageAsText();
 
@@ -177,9 +216,9 @@
 			navTree.getNodeByLabel("Applications").click();
 
 		}
-		// --- click ---
 
 
+		// Applications node 
 		{
 			// Whooo-hooo! So much to click through!
 
@@ -198,45 +237,518 @@
 			HtmlAnchor link = row.getFirstLinkFromColumn("Name");
 			link.click();
 		}
-  	// --- click ---
 
 
 		{
 			// Go back to applications Sumary screen.
 			navTree.getNodeByLabel("Applications").click();
 		}
-		// --- click ---
 
 
+		// Concrete appliction node.
 		{
+			// Deploy the EAR.
+			String earFilePath = System.getProperty(SYSPROP_TESTDATA_DIR) + "/ear/"+BASIC_EAR;
+			deployEar( earFilePath );
+
 			navTree.getNodeByLabel(NAV_EAR).click();
-		}
-		// --- click ---
 
+			ContentTableRow earRow = new ContentTable().getFirstRowContainingLink(BASIC_EAR);
+			assertTrue("Page doesn't list "+BASIC_EAR+" in Summary tab.", earRow != null );
 
+			// Go to the summary through listed item.
+			earRow.getLinkByLabel(BASIC_EAR).click();
+			// Check that we have the summary tab for the selected EAR.
+			assertTrue( "EAR name ("+BASIC_EAR+" not found in the content box.",
+				tabMenu.getTabContentBox().getElement().getTextContent().contains(BASIC_EAR) );
 
+			// Go to the summary through nav tree node.
+			NavTreeNode earNode = navTree.getNodeByLabel(NAV_EAR);
+			if( !earNode.isExpanded() ){
+				log.info("Expanding.");
+				earNode.getArrowLink().click();
+				Thread.sleep(2000);
+			}
+			navTree.getNodeByLabel(BASIC_EAR).click();
+			// Check that we have the summary tab for the selected EAR.
+			tabMenu.getTabContentBox().getElement().getTextContent().contains(BASIC_EAR);
 
+			undeployEar(BASIC_EAR);
 
+		}
+
+	
 	}// testNavigationToEar()
 
 
+
+
+
+
+	/**
+	 *  Assertion:  Verify the content of the Enterprise Application Summary tab
+	 *
+	 *
+	 * FAILS because clicking on the EAR name in list brings us to the root node Summary.
+	 * https://jira.jboss.org/jira/browse/EMBJOPR-80
+	 *
+	 * junit.framework.ComparisonFailure: expected:<eardeployment.ear> but was:<ondra-redhat>
+     at org.jboss.jopr.jsfunit.as5.EarTest.testEarSummaryTab(EarTest.java:323)
+	 */
+	public void DISABLEDtestEarSummaryTab() throws EmbJoprTestException, IOException, Exception {
+
+		final int DEPLOY_TIMEOUT_SEC = 10;
+
+		// Deploy the EAR
+		String earFilePath = System.getProperty(SYSPROP_TESTDATA_DIR) + "/ear/"+BASIC_EAR;
+		deployEar( earFilePath );
+
+		// Wait until the EAR appears...
+		new ActiveConditionChecker(new DescribedCondition("EAR appears in Summary tab list") {
+			public boolean isTrue() throws Exception {
+				// Refresh, then check.
+				navTree.getNodeByLabel(NAV_EAR).click();
+				ContentTableRow earRow = new ContentTable().findFirstRowContainingLink(BASIC_EAR);
+				return null != earRow;
+			}
+		}).dumpPageOnTimeout(this).throwOnTimeout().waitWithTimeout(2000, 5);
+
+		
+		ContentTableRow earRow = new ContentTable().getFirstRowContainingLink(BASIC_EAR);
+
+		// Wait until the Status is "UP".
+		// TODO: Replace with ActiveConditionChecker.
+		int maxLoops = DEPLOY_TIMEOUT_SEC;
+		do {
+			String statusText = earRow.getCellTextByColumnName("Status");
+			log.debug("EAR Status: "+statusText);
+			if( "UP".equals(statusText) )
+				break;
+
+			// Refresh page after 1 second.
+			navTree.getNodeByLabel(NAV_EAR).click();
+			earRow = new ContentTable().getFirstRowContainingLink(BASIC_EAR);
+
+			// We don't want an infinite loop by mistake.
+			if( maxLoops-- <= 0 ){
+				throw new EmbJoprTestException("EAR "+BASIC_EAR+" not UP after "+DEPLOY_TIMEOUT_SEC+" seconds.");
+			}
+		} while( true );
+
+		// FAILS because of EMBJOPR-80.
+		earRow.getLinkByLabel(BASIC_EAR).click();
+
+
+		// Check the values in info table(s)
+
+		// General Properties
+		ContentInfoTable infoTable = new ContentInfoTable(
+						tabMenu.getTabContentBox().getTableUnderHeader("General Properties").getElement() );
+		Properties props = infoTable.getProperties();
+
+		assertEquals(BASIC_EAR, props.getProperty("Name").trim());
+		//assertEquals("?", props.getProperty("Version")); // TODO: Where does RHQ get the version from?
+		// TODO: Fill JIRA? Description of EAR should be taken from application.xml <display-name>
+		//assertEquals("JBossTest Ear Deployment Testsuite", props.getProperty("Description"));
+
+
+		// Resource Traits
+		infoTable = new ContentInfoTable(
+						tabMenu.getTabContentBox().getTableUnderHeader("Resource Traits").getElement() );
+		props = infoTable.getProperties();
+
+
+		String path = System.getProperty(SYSPROP_DEPLOY_DIR)+"/"+BASIC_EAR;
+		assertEquals(path, props.getProperty("Path").trim());
+		
+		assertEquals("no", props.getProperty("Exploded?").trim());
+
+		// Metrics Summary 
+		infoTable = new ContentInfoTable(
+						tabMenu.getTabContentBox().getTableUnderHeader("Metrics Summary").getElement() );
+		// (nothing here yet)
+
+
+		// Undeploy the EAR
+		undeployEar( BASIC_EAR );
+
+	}// testEarSummary()
+
+
+
+	/**
+	 * 
+	 * @throws java.io.IOException
+	 * @throws org.jboss.jopr.jsfunit.exceptions.HtmlElementNotFoundException
+	 *
+	 * PASSED.
+	 */
+	public void testEarConfigurationTab() throws IOException, EmbJoprTestException {
+
+		// Deploy the EAR.
+		String earFilePath = System.getProperty(SYSPROP_TESTDATA_DIR) + "/ear/"+BASIC_EAR;
+		deployEar( earFilePath );
+
+		navTree.getNodeByLabel(NAV_EAR).click();
+		waitActivelyForDeployment(DeployableTypes.EAR, BASIC_EAR, 3000, 15);
+
+		ContentTableRow earRow = new ContentTable().getFirstRowContainingLink(BASIC_EAR);
+
+		// TODO: Finish
+
+		undeployEar(BASIC_EAR);
+
+	}
+
+
+	/**
+	 *
+	 * @throws java.io.IOException
+	 * @throws org.jboss.jopr.jsfunit.exceptions.HtmlElementNotFoundException
+	 *
+	 * PASSED.
+	 */
+	public void testDeployUnpackedEar() throws IOException, EmbJoprTestException {
+
+
+		//DebugUtils.writeFile("sysProp.txt", System.getProperties().toString());///
+
+		// Deploy the unpacked EAR.
+		// We have to use hotdeploy - can't upload a directory.
+		unzipToDeployDir("ear/"+EAR_UNPACKED_ZIP, "");
+		// Loop, wait for the app to appear.
+		waitActivelyForDeployment( DeployableTypes.EAR, EAR_UNPACKED, 5000, 18 );
+
+
+		navTree.getNodeByLabel(NAV_EAR).click();
+
+		ContentTableRow earRow = new ContentTable().getFirstRowContainingLink(EAR_UNPACKED);
+
+		// TODO: Finish
+
+		// TODO: DeploymentUtils, DeployableTypes, isAvailable enum inner classes
+
+		// TODO: Preliminary test - check system properties, their validity, java version, etc.
+
+	}
+
+
+
+	/**
+	 * Waits for the deployable to be in the UP State.
+	 *
+	 * @param type  Type of deployable - EAR, WAR, SAR, ...
+	 * @param name  Name of the deployable, like 'hello.war'.
+	 * @throws org.jboss.jopr.jsfunit.exceptions.EmbJoprTestException
+	 * @throws java.io.IOException
+	 */
+	private void waitActivelyForDeployment(
+						final DeployableTypes type, final String name,
+						int intervalMS, int retries
+					)
+					throws EmbJoprTestException, IOException
+	{
+		try {
+			String conditionDesc = type.name()+" "+name+" appears in embjopr as deployed";
+			boolean deployedSuccessfuly =
+			new ActiveConditionChecker( new DescribedCondition(conditionDesc) {
+				public boolean isTrue() throws HtmlElementNotFoundException, IOException {
+					return new DeploymentUtils().isDeployedAccordingToEmbJopr( type, name );
+				}
+			} ).dumpPageOnTimeout(this).throwOnTimeout().waitWithTimeout( intervalMS, retries );
+		}
+		catch( EmbJoprTestException ex ){ throw ex; }
+		catch( IOException ex ){ throw ex; }
+		// Wrap all exceptions to EmbJoprTestException.
+		catch( Exception ex ){
+			throw new EmbJoprTestException("Exception thrown while actively waiting for condition.", ex);
+		}
+	}
+
+
+	/**
+	 * Actively waits for a given condition.
+	 * @see Condition
+	 */
+	private class ActiveConditionChecker {
+
+		Condition condition;
+		private boolean dumpPageOnTimout = false;
+		private boolean throwExceptionOnTimout = false;
+		private EmbjoprTestCase test;
+
+		public ActiveConditionChecker(Condition condition) {
+			this.condition = condition;
+		}
+
+		@SuppressWarnings("empty-statement")
+		public boolean waitWithTimeout( int msInterval, int retries ) throws Exception {
+
+			while( retries-- > 0 ){
+				if( this.condition.isTrue() )
+					return true;
+				try {
+					Thread.sleep(msInterval);
+				} catch (InterruptedException ex){
+					;
+				}
+			}
+
+			// While ended, thus we reached the "timeout".
+
+			if( this.dumpPageOnTimout ){
+				try {
+					// Since this is still inner class, we could use 'this'.
+					//DebugUtils.writeFile(test.getName()	+ ".html", test.getClient().getPageAsText());///
+				} catch (Exception ex) { log.error("Can't dump page.", ex); }
+			}
+
+			if( this.throwExceptionOnTimout ){
+				String message = "Timeout expired while waiting for condition: "+condition.getDescription();
+				throw new EmbJoprTestException(message);
+			}
+
+			return false;
+		}
+
+		/** If called, exception is thrown if the timeout expires. */
+		private ActiveConditionChecker throwOnTimeout( /*String conditionDesc*/ ){
+			this.throwExceptionOnTimout = true;
+			//this.conditionDesc = conditionDesc;
+			return this;
+		}
+
+		// This has nothing to do with condition checking, but is convenient shorthand...
+		private ActiveConditionChecker dumpPageOnTimeout(EmbjoprTestCase test) {
+			this.dumpPageOnTimout = true;
+			this.test = test;
+			return this;
+		}
+
+	}
+
+	/** Condition for ActiveConditionChecker */
+	public interface Condition {
+		public String getDescription();
+		public boolean isTrue() throws Exception;
+	}
+
+	/** Half-implementation of Condition - takes care of the description. */
+	public abstract class DescribedCondition implements Condition {
+		private String description;
+		public DescribedCondition( String description ){
+			this.description = StringUtils.defaultIfEmpty(description, "(undescribed)");
+		}
+		public String getDescription() {			return this.description;		}
+	}
+
+
+
+
+
+
+	/**
+	 * Utilities for performing and checking deployment.
+	 * In the future, it should be general interface like
+	 *   boolean isDeployed( DeployableType type, String name ).
+	 */
+	protected class DeploymentUtils {
+
+		/**
+		 * Returns true if EmbJopr lists a deployable of given type and name,
+		 * and it's State is UP; false otherwise.
+		 */
+		private boolean isDeployedAccordingToEmbJopr( DeployableTypes type, String deployableName )
+						throws HtmlElementNotFoundException, IOException
+		{
+			// Refresh / go to the appropriate page.
+			navTree.getNodeByLabel( type.getNavTreeLabel() ).click();
+			ContentTableRow earRow = new ContentTable().findFirstRowContainingLink(deployableName);
+			if( null == earRow ){
+				log.debug("Row with "+deployableName+" not present.");
+				return false;
+			}
+
+			String statusText = earRow.getCellTextByColumnName("Status");
+			if( "UP".equals(statusText) ){
+				return true;
+			}else{
+				log.debug("Row with "+deployableName+" has Status == '"+statusText+"' != UP.");
+				return false;
+			}
+		}
+		
+		/**
+		 * Returns true if there's a file of the given name in server's deploy dir;
+		 * false otherwise.
+		 */
+		private boolean isDeployedAccordingToFileSystem( DeployableTypes type, String name )
+		{
+			String deployPath = System.getProperty(SYSPROP_DEPLOY_DIR);
+			String fileName = deployPath+"/"+name;
+			return (new File(fileName)).exists();
+		}
+
+		private void undeployViaFileSystem( String name ) throws EmbJoprTestException{
+			String deployPath = System.getProperty(SYSPROP_DEPLOY_DIR);
+			String fileName = deployPath+"/"+name;
+			File fileToDelete = new File(fileName);
+
+			if( !fileToDelete.exists() )
+				throw new EmbJoprTestException("Deployable doesn't exist: "+fileName);
+
+			if(fileToDelete.isFile()){
+				if( !fileToDelete.delete() ){
+					throw new EmbJoprTestException("Unable to delete: "+fileName);
+				}
+			}else if(fileToDelete.isDirectory()){
+				deleteDirectory(fileToDelete);
+			}
+
+
+		}
+
+	}
+
+
+	// TODO: Move to utils
+	/**
+	 * Unzips given archive from testdata dir to server's deploy/ dir.
+	 * @param relativeArchivePath  Path of the archive relative to testdata dir.
+	 * @param relativeDestDir      Path of the destination dir relative to deploy dir.
+	 */
+	private void unzipToDeployDir( String relativeArchivePath, String relativeDestDir )
+					throws FileNotFoundException, IOException
+	{
+
+		String destDir = System.getProperty(SYSPROP_DEPLOY_DIR)+"/"+relativeDestDir;
+		String archivePath = System.getProperty(SYSPROP_TESTDATA_DIR)+"/"+relativeArchivePath;
+
+		log.info("Unzipping '"+archivePath+"' to '"+destDir+"'.");
+
+		unzipArchive( archivePath, destDir );
+	}
+
+
+	
+	/**
+	 * Unzips archive from the given path to the given destination dir.
+	 */
+	private void unzipArchive(String archivePath, String destDir)
+					throws FileNotFoundException, IOException
+	{
+
+		FileInputStream fis = new FileInputStream( archivePath );
+		ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));
+
+		ZipEntry entry;
+		while( null != (entry = zin.getNextEntry()) ){
+
+			if(entry.isDirectory()) {
+				// Assume directories are stored parents first then children.
+				log.info("Extracting directory: " + entry.getName());
+				// This is not robust, just for demonstration purposes.
+				(new File(destDir +"/"+ entry.getName())).mkdir();
+				continue;
+			}
+
+			log.info("Extracting file: " + entry.getName());
+
+			final int BUFFER = 2048;
+			FileOutputStream fos = new FileOutputStream( destDir +"/"+ entry.getName());
+			BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
+
+			int count;
+			byte[] data = new byte[BUFFER];
+			while ((count = zin.read(data, 0, BUFFER)) != -1) {
+				 dest.write(data, 0, count);
+			}
+			dest.flush();
+			dest.close();
+			zin.closeEntry();
+
+		}
+
+		zin.close();
+
+	}
+
+
+
+
+	// TODO: Move to utils
+	private void deleteFromDeployDir( String deployableName ) throws IOException{
+
+		String deployDir = System.getProperty(SYSPROP_DEPLOY_DIR);
+
+		File dirToDelete = new File( deployDir, deployableName);
+		// Just not to delete something accidentally...
+		assertTrue( deployDir.contains("/server/"));
+		// Check if not outside deploy dir.
+		if( !dirToDelete.getCanonicalPath().startsWith( deployDir ) )
+			throw new IllegalArgumentException(
+							" The resulting path is outside deploy dir: "+dirToDelete.getCanonicalPath());
+
+		log.info("Deleting '"+dirToDelete.getPath()+"'...");
+		//deleteDirectory( dirToDelete );
+	}
+
+
+
+  public static void deleteDirectory(File path) throws EmbJoprTestException
+	{
+		List<String> undeletableFiles = new ArrayList();
+		deleteDirectory(path, undeletableFiles);
+		if( !undeletableFiles.isEmpty() ){
+			throw new EmbJoprTestException("Couldn't delete following files: \n  "+
+							StringUtils.join(undeletableFiles, "\n  ") + "\n");
+		}
+	}
+
+  public static void deleteDirectory(File path, List<String> undeletableFiles)
+	{
+    if( path.exists() ) {
+      File[] files = path.listFiles();
+      for(int i=0; i<files.length; i++) {
+         if(files[i].isDirectory()) {
+           deleteDirectory(files[i], undeletableFiles );
+         }
+         else {
+           if( !files[i].delete() ){
+						 undeletableFiles.add(files[i].getAbsolutePath());
+					 }
+         }
+      }
+    }
+    if( ! path.delete() )
+			undeletableFiles.add( path.getAbsolutePath() );
+  }
+
 	private void deployEar( String earFilePath ) throws IOException
 	{
+		if( !(new File(earFilePath)).exists())
+			throw new FileNotFoundException(earFilePath);
 
+		log.info("Deploying: "+earFilePath);
+
 		// Navigate to Enterprise Archives
 		navTree.getNodeLink(NAV_EAR).click();
 
 		// click on the "Add new resource" button
 		client.click("actionHeaderForm:addNewContent");  // 404 if setThrowExceptionOnFailingStatusCode(true) above
 
-		// upload hellothere.war
+		// Upload the file
 		HtmlFileInput fileInput = (HtmlFileInput)client.getElement("createContentForm:file");
 		fileInput.setContentType("application/ear");
 		fileInput.setValueAttribute(earFilePath);
 		client.click("createContentForm:addButton");
+		sleep( 2000 );
+
+		// Log the message
+		logServerMessage("Something went wrong with deploy: ");
 	}
 
-	private void undeployEar( String earFileName ) throws IOException, EmbJoprTestException
+	private void undeployEar( String earFileName ) throws IOException, HtmlElementNotFoundException, ActionNotAvailableException
 	{
 
 		// Navigate to Enterprise Archives
@@ -247,9 +759,37 @@
 		HtmlButtonInput deleteButton = getAppDeleteButton( earFileName );
 		deleteButton.click();
 
+		// Log the message
+		logServerMessage("Something went wrong with undeploy: ");
 
+		// Sleep for 3 sec.
+		sleep( 3000 );
+
 	}
 
 
+	private void logServerMessage(){ logServerMessage(""); }
 
-}
+	private void logServerMessage( String warnPrefix ){
+		if( server.getFacesMessages().hasNext() ){
+			FacesMessage msg = server.getFacesMessages().next();
+			if( msg.getSeverity() == FacesMessage.SEVERITY_INFO ){
+				log.info( msg.getSummary() +"\n"+ msg.getDetail() );
+			}else{
+				log.warn( warnPrefix + msg.getSummary() +"\n"+ msg.getDetail() );
+			}
+		}
+	}
+
+	/** Calls Thread.sleep(ms), ignores the InterruptedException. */
+	@SuppressWarnings("empty-statement")
+	private void sleep( int ms ) {
+		try {
+			Thread.sleep(3000);
+		} catch (InterruptedException ex) {
+			; // We don't care, that's the purpose of this method.
+		}
+	}
+
+
+}// class EarTest




More information about the embjopr-commits mailing list