Author: fjuma
Date: 2009-01-19 14:19:33 -0500 (Mon, 19 Jan 2009)
New Revision: 111
Modified:
trunk/core/src/main/webapp/include/tabMenu.xhtml
trunk/core/src/main/webapp/secure/addMap.xhtml
trunk/core/src/main/webapp/secure/resourceInstanceOperation.xhtml
trunk/core/src/main/webapp/secure/resourceInstanceSummary.xhtml
trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java
trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/DatasourceTest.java
Log:
Added datasource creation tests, deletion tests, and some preliminary metrics tests that
are meant to be run specifically against AS5.
Added ID attributes to tags in some xhtml files.
Modified: trunk/core/src/main/webapp/include/tabMenu.xhtml
===================================================================
--- trunk/core/src/main/webapp/include/tabMenu.xhtml 2009-01-19 18:21:11 UTC (rev 110)
+++ trunk/core/src/main/webapp/include/tabMenu.xhtml 2009-01-19 19:19:33 UTC (rev 111)
@@ -53,7 +53,7 @@
<!-- ENABLED panel (can be viewed) -->
<h:panelGroup layout="block" rendered="#{activeTab ne
'summary'}">
<li>
- <s:link styleClass="" view="/secure/summary.xhtml"
propagation="end">
+ <s:link id="summaryTab" styleClass=""
view="/secure/summary.xhtml" propagation="end">
#{messages['tab.menu.summary']}
</s:link>
</li>
@@ -122,7 +122,7 @@
<h:panelGroup layout="block"
rendered="#{activeTab ne 'operation' and
navigationAction.enabledTabs.contains('operation')}">
<li>
- <s:link styleClass=""
view="/secure/resourceInstanceOperation.xhtml" propagation="end">
+ <s:link id="controlTab" styleClass=""
view="/secure/resourceInstanceOperation.xhtml" propagation="end">
#{messages['tab.menu.control']}
</s:link>
</li>
Modified: trunk/core/src/main/webapp/secure/addMap.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/addMap.xhtml 2009-01-19 18:21:11 UTC (rev 110)
+++ trunk/core/src/main/webapp/secure/addMap.xhtml 2009-01-19 19:19:33 UTC (rev 111)
@@ -53,7 +53,8 @@
<h:panelGrid columns="2" styleClass="buttons-table"
columnClasses="button-cell">
<h:commandButton
value="#{messages['resource.configuration.map.button.ok']}"
action="#{resourceConfigurationUIBean.addMap()}"
- styleClass="buttonmed"/>
+ styleClass="buttonmed"
+ id="okButton"/>
</h:panelGrid>
</h:form>
Modified: trunk/core/src/main/webapp/secure/resourceInstanceOperation.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/resourceInstanceOperation.xhtml 2009-01-19 18:21:11
UTC (rev 110)
+++ trunk/core/src/main/webapp/secure/resourceInstanceOperation.xhtml 2009-01-19 19:19:33
UTC (rev 111)
@@ -95,7 +95,7 @@
<h:outputText
value="#{messages['control.resourceInstance.error.noPrevious']}"
rendered="#{operationHistory eq null}"/>
-<h:form rendered="#{operationHistory ne null}">
+<h:form id="operationHistoryForm" rendered="#{operationHistory ne
null}">
<ui:remove>
<!-- NOTE: The below causes the results/error toggle panels to not display
properly. Uncomment when RichFaces
fixes whatever the problem is. (ips, 08/20/08) -->
Modified: trunk/core/src/main/webapp/secure/resourceInstanceSummary.xhtml
===================================================================
--- trunk/core/src/main/webapp/secure/resourceInstanceSummary.xhtml 2009-01-19 18:21:11
UTC (rev 110)
+++ trunk/core/src/main/webapp/secure/resourceInstanceSummary.xhtml 2009-01-19 19:19:33
UTC (rev 111)
@@ -78,7 +78,8 @@
<h:panelGroup
rendered="#{navigationAction.enabledTabs.contains('metric')}">
<h2>#{messages['summary.resourceInstance.metrics']}</h2>
- <rich:dataTable
value="#{summaryMeasurementDisplayList}"
+ <rich:dataTable id="dataTable"
+ value="#{summaryMeasurementDisplayList}"
var="md"
rowClasses="oddRow,evenRow"
columnClasses="rich-table-cell, rich-table-cell,
rich-table-cell-action">
@@ -90,7 +91,7 @@
</rich:columnGroup>
</f:facet>
<rich:column>#{summaryMeasurementDefinitionMap[md.measurementData.name].displayName}</rich:column>
-
<rich:column>#{md.measurementValueAndUnits}</rich:column>
+ <rich:column
id="measurementValue">#{md.measurementValueAndUnits}</rich:column>
<rich:column>#{summaryMeasurementDefinitionMap[md.measurementData.name].description}</rich:column>
</rich:dataTable>
</h:panelGroup>
Modified: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java 2009-01-19
18:21:11 UTC (rev 110)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/EmbjoprTestCase.java 2009-01-19
19:19:33 UTC (rev 111)
@@ -199,9 +199,11 @@
// Set each property
while(itr.hasNext()) {
String propertyName = (String)itr.next();
+
+ // Make sure the input is enabled
+ HtmlInput input = enableOrDisableFormInput(propertyName,
+ Boolean.TRUE);
- // Enable the input if it is currently disabled
- HtmlInput input = enableFormInput(propertyName);
assertFalse(input.isDisabled());
setFormInput(input, properties.get(propertyName));
@@ -209,44 +211,43 @@
}
/**
- * Enable the given input box or "Yes/No" radio button that corresponds
- * to the given property name on a resource configuration page. If the
- * input box/radio button is already enabled, do nothing.
- *
- * @return the enabled input element
+ * Attempt to enable or disable the given input box or "Yes/No" radio
button
+ * that corresponds to the given property name on a resource configuration
+ * page. Return the enabled/disabled input element.
+ * If the input box/radio button does not have an enable/disable checkbox,
+ * return the input element as is.
*/
- public HtmlInput enableFormInput(String propertyName) {
+ public HtmlInput enableOrDisableFormInput(String propertyName,
+ Boolean enableInput) {
HtmlForm form =
(HtmlForm)client.getElement("resourceConfigurationForm");
HtmlInput input =
(HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//"
- + propertyName + "']");
+ + propertyName + "']");
- assertNotNull("Form input for property "+propertyName+" not
found.", input);
+ assertNotNull("Form input for property " + propertyName + " not
found.", input);
boolean isRadioButton = input.getTypeAttribute().equals("radio");
String id = input.getId();
String xpath;
- if(input.isDisabled()) {
-
- // Find the enable/disable checkbox corresponding to this
- // input element.
- if(isRadioButton) {
+ // Look for an enable/disable checkbox corresponding to this
+ // input element.
+ if(isRadioButton) {
- xpath =
".//input[(a)onchange=\"setInputUnset(document.getElementById('"
- + id
- + "'),
this.checked);setInputUnset(document.getElementById('"
- + id.substring(0, id.lastIndexOf(":")) +
":1'), this.checked);\"]";
- } else {
- xpath =
".//input[(a)onchange=\"setInputUnset(document.getElementById('"
- + id + "'), this.checked);\"]";
- }
+ xpath =
".//input[(a)onchange=\"setInputUnset(document.getElementById('"
+ + id
+ + "'),
this.checked);setInputUnset(document.getElementById('"
+ + id.substring(0, id.lastIndexOf(":")) + ":1'),
this.checked);\"]";
+ } else {
+ xpath =
".//input[(a)onchange=\"setInputUnset(document.getElementById('"
+ + id + "'), this.checked);\"]";
+ }
- HtmlInput checkBox = (HtmlInput)form.getFirstByXPath(xpath);
- checkBox.setChecked(Boolean.FALSE);
- input =
(HtmlInput)form.getFirstByXPath(".//input[@ondblclick='//"
- + propertyName + "']");
+ HtmlInput checkBox = (HtmlInput)form.getFirstByXPath(xpath);
+
+ if(checkBox != null) {
+ checkBox.setChecked(!enableInput);
}
-
+
return input;
}
@@ -264,8 +265,8 @@
// Get the "No" radio button
input = (HtmlInput)client.getElement(id.substring(0,
- id.lastIndexOf(":"))
- + ":1");
+ id.lastIndexOf(":"))
+ + ":1");
}
input.setChecked(Boolean.TRUE);
@@ -274,7 +275,6 @@
}
}
-
/**
* Check that the given messages occur on the client side
* and server side.
@@ -297,6 +297,19 @@
}
/**
+ * Refresh the content under the given nav tree node.
+ */
+ public void refreshTreeNode(String nodeName) throws IOException {
+
+ // Collapse and then expand the nav tree node
+ ClickableElement nodeArrow = getNavTreeArrow(nodeName);
+ nodeArrow.click();
+
+ nodeArrow = getNavTreeArrow(nodeName);
+ nodeArrow.click();
+ }
+
+ /**
* This just checks that the JSFServerSession object was created.
*/
public void testServerSessionCreated() {
@@ -310,190 +323,168 @@
assertTrue(client != null);
}
+ /**
+ * Finds a row in the "details table" using the text in the Name column
+ * and returns the text from the Value column.
+ * @param name
+ * @return
+ */
+ public String getDetailsRowValue(String name) throws AssertException {
+ HtmlDivision contentDiv = (HtmlDivision) client.getElement("content");
+ List<?> valueTDs = contentDiv.getByXPath(
+
".//div[@class='tabmenubox']//td[contains(text(),'"+name+"']/following-sibling::td[1]");
+ //assertTrue( name + " row not found.", valueTDs.size() == 1 );
+ if( valueTDs.size() == 1 )
+ throw new AssertException( name + " row not found." );
+ String value = ((HtmlTableCell) valueTDs).getTextContent();
+ return value;
+ }
+ /**
+ * Returns the content element - <div id="content"> - which
contains whole page.
+ * Good as a start point for XPath queries - other elements usually have generated
IDs.
+ * Assertion fails if the element is not found.
+ * @return
+ */
+ public HtmlElement getContentElement() throws AssertException {
+ HtmlElement contentElement =
(HtmlElement)client.getElement("content");
+ //assertNotNull("Content <div> not found.", contentElement);
+ if( null == contentElement )
+ throw new AssertException( "Content <div> not found." );
+ return contentElement;
+ }
+ /**
+ * Convenience method, calls getElementsByXPath() with content element.
+ * @param sXPath
+ * @return
+ */
+ public List<? extends HtmlElement> getElementsByXPath(String sXPath ) throws
AssertException {
+ //return (List<? extends HtmlElement>)
getContentElement().getByXPath(sXPath);
+ return getElementsByXPath( getContentElement(), sXPath );
+ }
+ /**
+ * Retuns a list of elements chosen by XPath, with the given element as context
node.
+ * @param xPathContextElement
+ * @param sXPath
+ * @return
+ */
+ public List<? extends HtmlElement> getElementsByXPath(
+ HtmlElement xPathContextElement, String sXPath )
+ throws AssertException
+ {
+ if( null == xPathContextElement ){
+ throw new AssertException("Given XPath context element is null.");
+ }
+ return (List<? extends HtmlElement>)
xPathContextElement.getByXPath(sXPath);
+ }
+ /**
+ * Returns the first element in the list returned by getElementsByXPath(String sXPath
).
+ * @param sXPath
+ * @return
+ */
+ public HtmlElement getFirstElementByXPath( HtmlElement xPathContext, String sXPath )
throws AssertException {
+ List<? extends HtmlElement> elementsByXPath =
getElementsByXPath(xPathContext, sXPath);
+ if( elementsByXPath.size() == 0 ){
+ throw new RuntimeException("XPath expression found no elements:
"+sXPath);
+ // Exception is better - will get the stack trace.
+ //fail("XPath expression found no elements: "+sXPath);
+ }
+ return elementsByXPath.get(0);
+ }
+ /**
+ * Convenience method - calls getFirstElementByXPath() with content div as context.
+ * @param sXPath
+ * @return
+ */
+ public HtmlElement getFirstElementByXPath( String sXPath ) throws AssertException{
+ return getFirstElementByXPath( getContentElement(), sXPath );
+ }
+ /**
+ * Retrieves an input element from a named row of a table in a form.
+ * Supposes that the form is in the "tabmenubox" or
"notabmenubox" div.
+ * @param sRowName
+ * @return
+ * @throws org.jboss.jopr.jsfunit.AssertException
+ */
+ public HtmlInput getFormInputByRowName(String sRowName) throws AssertException {
+ try {
+ HtmlInput input = (HtmlInput) getFirstElementByXPath(
+ getTabMenuBoxElement(),
+
".//td[contains(text(),'"+sRowName+"')]/following-sibling::td[@class='property-value-cell']//input"
+ );
+ if( null == input ){
+ throw new AssertException("Input for value "+sRowName+"
not found.");
+ }
+ return input;
+ }
+ catch(AssertException ex){
+ //throw new AssertException("Row with name
\""+sRowName+"\" not found.", ex);
+ throw ex;
+ }
+ }
- /**
- * Finds a row in the "details table" using the text in the Name column
- * and returns the text from the Value column.
- * @param name
- * @return
- */
- public String getDetailsRowValue(String name) throws AssertException {
- HtmlDivision contentDiv = (HtmlDivision) client.getElement("content");
- List<?> valueTDs = contentDiv.getByXPath(
- ".//div[@class='tabmenubox']//td[contains(text(),'"+name+"']/following-sibling::td[1]");
- //assertTrue( name + " row not found.", valueTDs.size() == 1 );
- if( valueTDs.size() == 1 )
- throw new AssertException( name + " row not found." );
- String value = ((HtmlTableCell) valueTDs).getTextContent();
- return value;
- }
+ /**
+ * Retrieves a named row of a table in the "right side of the page".
+ * Supposes that the table is in the "tabmenubox" or
"notabmenubox" div.
+ * Uses getTabMenuBoxElement() to get that div.
+ * @param sRowName
+ * @return
+ * @throws org.jboss.jopr.jsfunit.AssertException
+ */
+ public HtmlTableRow getRowByName(String sRowName) throws AssertException {
+ HtmlTableRow row = (HtmlTableRow) getFirstElementByXPath(
+ getTabMenuBoxElement(),
+
".//td[contains(text(),'"+sRowName+"')]/ancestor::tr"
+ );
+ if( null == row ){
+ throw new AssertException("Row for value "+sRowName+" not
found.");
+ }
+ return row;
+ }
+ /**
+ * Returns the element which contains the "right side of the page".
+ * <div class="tabmenubox"> element exists on each page that shows
resource's details.
+ * <div class="notabmenubox"> element exists on each page with form
for resource's properties editation.
+ * @return
+ * @throws org.jboss.jopr.jsfunit.AssertException
+ */
+ public HtmlElement getTabMenuBoxElement() throws AssertException {
+ return getFirstElementByXPath(".//div[@class='tabmenubox' or
@class='notabmenubox']");
+ }
- /**
- * Returns the content element - <div id="content"> - which
contains whole page.
- * Good as a start point for XPath queries - other elements usually have generated
IDs.
- * Assertion fails if the element is not found.
- * @return
- */
- public HtmlElement getContentElement() throws AssertException {
- HtmlElement contentElement = (HtmlElement)client.getElement("content");
- //assertNotNull("Content <div> not found.", contentElement);
- if( null == contentElement )
- throw new AssertException( "Content <div> not found." );
- return contentElement;
- }
+ /**
+ * Returns an integer part of the beginning of the given string.
+ * @param s
+ * @return Integer with the value of numerical part of the string,
+ * or null if there are no digits at the beginning.
+ */
+ public Integer integerFromString(String s) {
+ int pos;
+ for( pos = 0; pos < s.length(); pos++ ){
+ char ch = s.charAt(0);
+ if( '0' > ch || ch > '9' )
+ break;
+ }
+ if( pos == 0 )
+ return null;
- /**
- * Convenience method, calls getElementsByXPath() with content element.
- * @param sXPath
- * @return
- */
- public List<? extends HtmlElement> getElementsByXPath(String sXPath ) throws
AssertException {
- //return (List<? extends HtmlElement>) getContentElement().getByXPath(sXPath);
- return getElementsByXPath( getContentElement(), sXPath );
- }
+ try{
+ int val = Integer.parseInt( s.substring( 0, pos ) );
+ return val;
+ }catch( NumberFormatException ex ){
+ return null;
+ }
-
- /**
- * Retuns a list of elements chosen by XPath, with the given element as context node.
- * @param xPathContextElement
- * @param sXPath
- * @return
- */
- public List<? extends HtmlElement> getElementsByXPath(
- HtmlElement xPathContextElement, String sXPath )
- throws AssertException
- {
- if( null == xPathContextElement ){
- throw new AssertException("Given XPath context element is null.");
- }
-
- return (List<? extends HtmlElement>) xPathContextElement.getByXPath(sXPath);
- }
-
-
- /**
- * Returns the first element in the list returned by getElementsByXPath(String sXPath
).
- * @param sXPath
- * @return
- */
- public HtmlElement getFirstElementByXPath( HtmlElement xPathContext, String sXPath )
throws AssertException {
-
- List<? extends HtmlElement> elementsByXPath = getElementsByXPath(xPathContext,
sXPath);
- if( elementsByXPath.size() == 0 ){
- throw new RuntimeException("XPath expression found no elements: "+sXPath);
- // Exception is better - will get the stack trace.
- //fail("XPath expression found no elements: "+sXPath);
- }
- return elementsByXPath.get(0);
- }
-
-
- /**
- * Convenience method - calls getFirstElementByXPath() with content div as context.
- * @param sXPath
- * @return
- */
- public HtmlElement getFirstElementByXPath( String sXPath ) throws AssertException{
- return getFirstElementByXPath( getContentElement(), sXPath );
- }
-
-
- /**
- * Retrieves an input element from a named row of a table in a form.
- * Supposes that the form is in the "tabmenubox" or "notabmenubox"
div.
- * @param sRowName
- * @return
- * @throws org.jboss.jopr.jsfunit.AssertException
- */
- public HtmlInput getFormInputByRowName(String sRowName) throws AssertException {
- try {
- HtmlInput input = (HtmlInput) getFirstElementByXPath(
- getTabMenuBoxElement(),
- ".//td[contains(text(),'"+sRowName+"')]/following-sibling::td[@class='property-value-cell']//input"
- );
- if( null == input ){
- throw new AssertException("Input for value "+sRowName+" not
found.");
- }
- return input;
- }
- catch(AssertException ex){
- //throw new AssertException("Row with name \""+sRowName+"\"
not found.", ex);
- throw ex;
- }
- }
-
-
- /**
- * Retrieves a named row of a table in the "right side of the page".
- * Supposes that the table is in the "tabmenubox" or "notabmenubox"
div.
- * Uses getTabMenuBoxElement() to get that div.
- * @param sRowName
- * @return
- * @throws org.jboss.jopr.jsfunit.AssertException
- */
- public HtmlTableRow getRowByName(String sRowName) throws AssertException {
- HtmlTableRow row = (HtmlTableRow) getFirstElementByXPath(
- getTabMenuBoxElement(),
- ".//td[contains(text(),'"+sRowName+"')]/ancestor::tr"
- );
- if( null == row ){
- throw new AssertException("Row for value "+sRowName+" not
found.");
- }
- return row;
- }
-
-
- /**
- * Returns the element which contains the "right side of the page".
- * <div class="tabmenubox"> element exists on each page that shows
resource's details.
- * <div class="notabmenubox"> element exists on each page with form for
resource's properties editation.
- * @return
- * @throws org.jboss.jopr.jsfunit.AssertException
- */
- public HtmlElement getTabMenuBoxElement() throws AssertException {
- return getFirstElementByXPath(".//div[@class='tabmenubox' or
@class='notabmenubox']");
- }
-
-
-
-
- /**
- * Returns an integer part of the beginning of the given string.
- * @param s
- * @return Integer with the value of numerical part of the string,
- * or null if there are no digits at the beginning.
- */
- public Integer integerFromString(String s) {
- int pos;
- for( pos = 0; pos < s.length(); pos++ ){
- char ch = s.charAt(0);
- if( '0' > ch || ch > '9' )
- break;
- }
-
- if( pos == 0 )
- return null;
-
- try{
- int val = Integer.parseInt( s.substring( 0, pos ) );
- return val;
- }catch( NumberFormatException ex ){
- return null;
- }
-
- }
-
-
+ }
}
Modified: trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/DatasourceTest.java
===================================================================
--- trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/DatasourceTest.java 2009-01-19
18:21:11 UTC (rev 110)
+++ trunk/jsfunit/src/test/java/org/jboss/jopr/jsfunit/as5/DatasourceTest.java 2009-01-19
19:19:33 UTC (rev 111)
@@ -38,6 +38,7 @@
import javax.management.ObjectName;
import java.util.Set;
import java.util.Iterator;
+import java.util.ArrayList;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
@@ -50,7 +51,6 @@
import javax.sql.DataSource;
import javax.naming.Context;
import java.sql.SQLException;
-import org.jboss.jopr.jsfunit.EmbjoprTestCase;
/**
* When complete, this class will contain tests for creating,
@@ -67,6 +67,8 @@
private final String NO_TX_DATASOURCE="No TX Datasources";
private final String XA_DATASOURCE="XA Datasources";
+ private final String MAX_ITEMS_PER_PAGE="20";
+
/**
* Create a new datasource using the given type, template, and properties.
*
@@ -99,12 +101,55 @@
private void deleteDatasource(String datasourceName) throws IOException {
HtmlAnchor datasourceLink = getNavTreeLink("Datasources");
datasourceLink.click();
+
+ HtmlSelect menu = (HtmlSelect)client.getElement("currentPageSize");
+ if(menu != null) {
+ menu.setSelectedAttribute(MAX_ITEMS_PER_PAGE, Boolean.TRUE);
+ }
+
HtmlButtonInput deleteButton = getDeleteButton("categorySummaryForm",
datasourceName);
deleteButton.click();
}
/**
+ * Make sure that the metrics corresponding to the given datasource
+ * are correct.
+ *
+ * @param metricsMap maps metric names to the expected metric values.
+ */
+ private void checkMetrics(String datasourceName,
+ String datasourceType,
+ Map<String, String> metricsMap) throws IOException {
+
+ refreshTreeNode("Datasources");
+ ClickableElement datasourceTypeArrow = getNavTreeArrow(datasourceType);
+ datasourceTypeArrow.click();
+
+ HtmlAnchor datasource = getNavTreeLink(datasourceName);
+ datasource.click();
+
+ // Check values under the "Metrics" tab
+ HtmlAnchor metricsLink = (HtmlAnchor)client.getElement("metricsTab");
+ metricsLink.click();
+
+ for(Iterator i = metricsMap.keySet().iterator(); i.hasNext();) {
+ String metricName = (String)i.next();
+ assertEquals(metricsMap.get(metricName),
+ getMetricValueFromTable(metricName, "dataTable"));
+ }
+
+ // Check values under the "Summary" tab
+ HtmlAnchor summaryLink = (HtmlAnchor)client.getElement("summaryTab");
+ summaryLink.click();
+
+ assertEquals(metricsMap.get("Available Connection Count"),
+ getMetricValueFromTable("Available Connection Count",
"dataTable"));
+ assertEquals(metricsMap.get("Connection Count"),
+ getMetricValueFromTable("Connection Count",
"dataTable"));
+ }
+
+ /**
* Use JMX to check if the datasource given by datasourceName is
* deployed.
*/
@@ -227,6 +272,51 @@
}
/**
+ * containsElement returns whether or not the *-ds.xml file corresponding
+ * to the datasource given by jndiName contains the given element.
+ */
+ private boolean containsElement(String jndiName, String elementName) {
+ try {
+ File file = new File(System.getProperty("jsfunit.deploy.dir")
+ + "/" + jndiName + "-ds.xml");
+
+ SAXBuilder builder = new SAXBuilder();
+ Document doc = builder.build(file);
+
+ Element root = doc.getRootElement();
+ assertTrue(root.getName().equals("datasources"));
+ return root.getChild(elementName) != null;
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Perform the given operation on the given datasource.
+ */
+ private void performDatasourceOperation(String datasourceName,
+ String datasourceType,
+ String operationName) throws IOException {
+
+ refreshTreeNode("Datasources");
+ ClickableElement datasourceTypeArrow = getNavTreeArrow(datasourceType);
+ datasourceTypeArrow.click();
+
+ HtmlAnchor datasourceLink = getNavTreeLink(datasourceName);
+ datasourceLink.click();
+
+ HtmlAnchor controlLink = (HtmlAnchor)client.getElement("controlTab");
+ controlLink.click();
+
+ HtmlForm form = (HtmlForm)client.getElement("operation_form");
+ String xpath = ".//input[@value=\"" + operationName +
"\"]";
+
+ HtmlButtonInput operationButton = (HtmlButtonInput)form.getFirstByXPath(xpath);
+ operationButton.click();
+ }
+
+
+ /**
* Connect to the database identified by the given JNDI name,
* using the given username and password. Return the Connection
* object.
@@ -248,6 +338,76 @@
}
/**
+ * Create a basic Local TX Datasource. Return the mapping of property
+ * names to property values.
+ */
+ private Map<String, String> createLocalTXDatasource(String datasourceName)
throws IOException {
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put("jndi-name", datasourceName);
+ propertiesMap.put("max-pool-size", "20");
+ propertiesMap.put("min-pool-size", "5");
+ propertiesMap.put("user-name", "sa");
+ propertiesMap.put("password", "");
+ propertiesMap.put("domain", "HsqlDbRealm");
+ propertiesMap.put("blocking-timeout-millis", "35000");
+ propertiesMap.put("idle-timeout-minutes", "20");
+ propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+ propertiesMap.put("connection-url",
"jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB");
+
+ createDatasource(LOCAL_TX_DATASOURCE, "default__Local TX Datasource",
+ propertiesMap);
+ client.click("resourceConfigurationForm:saveButton");
+
+ return propertiesMap;
+ }
+
+ /**
+ * Create a basic No TX Datasource. Return the mapping of property
+ * names to property values.
+ */
+ private Map<String, String> createNoTXDatasource(String datasourceName) throws
IOException {
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put("jndi-name", datasourceName);
+ propertiesMap.put("prefill", "true");
+ propertiesMap.put("track-connection-by-tx", "false");
+ propertiesMap.put("max-pool-size", "20");
+ propertiesMap.put("min-pool-size", "5");
+ propertiesMap.put("blocking-timeout-millis", "55000");
+ propertiesMap.put("idle-timeout-minutes", "60");
+ propertiesMap.put("noTxSeparatePools", "true");
+ propertiesMap.put("user-name", "sa");
+ propertiesMap.put("password", "");
+ propertiesMap.put("domain", "HsqlDbRealm");
+ propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+ propertiesMap.put("connection-url",
"jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB");
+
+ createDatasource(NO_TX_DATASOURCE, "default__No TX Datasource",
+ propertiesMap);
+ client.click("resourceConfigurationForm:saveButton");
+
+ return propertiesMap;
+ }
+
+ /**
+ * Create a basic XA Datasource. Return the mapping of property
+ * name to property values.
+ */
+ private Map<String, String> createXADatasource(String datasourceName) throws
IOException {
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put("jndi-name", datasourceName);
+ propertiesMap.put("xa-datasource-class",
"org.postgresql.xa.PGXADataSource");
+ propertiesMap.put("xa-resource-timeout", "36000");
+ propertiesMap.put("max-pool-size", "15");
+ propertiesMap.put("min-pool-size", "6");
+
+ createDatasource(XA_DATASOURCE, "default__XA Datasource",
+ propertiesMap);
+ client.click("resourceConfigurationForm:saveButton");
+
+ return propertiesMap;
+ }
+
+ /**
* @return the suite of tests being tested
*/
public static Test suite()
@@ -256,7 +416,7 @@
}
/*
- * Some preliminary creation tests
+ * CREATION TESTS:
*/
/**
@@ -267,7 +427,7 @@
Map<String, String> propertiesMap = new HashMap<String, String>();
// The properties we want to configure
- propertiesMap.put("jndi-name", "TestDS");
+ propertiesMap.put("jndi-name", "CreationTestDS");
propertiesMap.put("user-name", "testUser");
propertiesMap.put("password", "password");
propertiesMap.put("min-pool-size", "5");
@@ -287,7 +447,7 @@
propertiesMap.put("background-validation-millis", "15000");
propertiesMap.put("use-try-lock", "61000");
propertiesMap.put("prefill", "true");
- propertiesMap.put("share-prepared-statements", "false");
+ propertiesMap.put("share-prepared-statements", "false");
createDatasource(LOCAL_TX_DATASOURCE,
"default__Local TX Datasource",
@@ -306,13 +466,10 @@
// TODO: need to verify that appropriate default values were
// set for properties that were not specified above
-
+
// Clean up
deleteDatasource(propertiesMap.get("jndi-name"));
- expectedMessage = "Successfully deleted Local TX Datasource '"
- + propertiesMap.get("jndi-name") +
"'";
- checkClientAndServerMessages(expectedMessage, expectedMessage, false);
- }
+ }
/**
* Attempt to create a new datasource but leave at least one required
@@ -338,7 +495,7 @@
+ "or more properties",
"Value is required",
true);
- }
+ }
/**
* Attempt to create a new datasource but set a property value
@@ -391,5 +548,217 @@
"Value is not a valid integer",
true);
}
+
+ /**
+ * Attempt to create a new datasource but set a property value to a value
+ * that is the correct type but is not an allowed value for that
+ * property. An error should occur.
+ */
+ public void testCreateDatasourcePropertyNotAllowed() throws IOException {
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put("jndi-name", "InvalidDS");
+ propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+ propertiesMap.put("connection-url", "jdbc:hsqldb:.");
+
+ // This number is a valid integer but is below the
+ // allowable minimum value
+ propertiesMap.put("max-pool-size", "-25");
+
+ createDatasource(NO_TX_DATASOURCE, "default__No TX Datasource",
+ propertiesMap);
+ client.click("resourceConfigurationForm:saveButton");
+
+ // Check for the appropriate error messages
+ checkClientAndServerMessages("An invalid value was specified for one "
+ + "or more properties",
+ "Value is less than allowable minimum",
+ true);
+ }
+
+ /**
+ * Attempt to create a new datasource using a JNDI name that already exists.
+ * An error should occur.
+ */
+ public void testCreateDatasourceDuplicateJNDIName() throws IOException {
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ propertiesMap.put("jndi-name", "DefaultDS");
+ propertiesMap.put("driver-class", "org.hsqldb.jdbcDriver");
+ propertiesMap.put("connection-url", "jdbc:hsqldb:.");
+
+ createDatasource(LOCAL_TX_DATASOURCE, "default__Local TX Datasource",
+ propertiesMap);
+ client.click("resourceConfigurationForm:saveButton");
+
+ // Check for the appropriate error messages
+ String expectedMessage = "Failed to add Resource (see app server log for
"
+ + "additional details): A Local TX Datasource
named "
+ + "'DefaultDS' already exists";
+ checkClientAndServerMessages(expectedMessage, expectedMessage, true);
+ }
+
+ /*
+ * DELETION TESTS:
+ */
+
+ /**
+ * Remove a Local TX Datasource.
+ */
+ public void testDeleteLocalTXDatasource() throws Exception {
+ Map<String, String> propertiesMap =
createLocalTXDatasource("DeleteLocalTXDS");
+
+ deleteDatasource(propertiesMap.get("jndi-name"));
+
+ // Check for the appropriate success messages
+ String expectedMessage = "Successfully deleted Local TX Datasource
'"
+ + propertiesMap.get("jndi-name") +
"'";
+ checkClientAndServerMessages(expectedMessage, expectedMessage, false);
+
+ assertFalse(isDatasourceDeployed(propertiesMap.get("jndi-name"),
+ LOCAL_TX_DATASOURCE));
+
+ // Make sure the entry was removed from the -ds.xml file
+ assertFalse(containsElement(propertiesMap.get("jndi-name"),
+ "local-tx-datasource"));
+ }
+
+ /**
+ * Remove a No TX Datasource.
+ */
+ public void testDeleteNoTXDatasource() throws Exception {
+ Map<String, String> propertiesMap =
createNoTXDatasource("DeleteNoTXDS");
+
+ deleteDatasource(propertiesMap.get("jndi-name"));
+
+ // Check for the appropriate success messages
+ String expectedMessage = "Successfully deleted No TX Datasource '"
+ + propertiesMap.get("jndi-name") +
"'";
+ checkClientAndServerMessages(expectedMessage, expectedMessage, false);
+
+ assertFalse(isDatasourceDeployed(propertiesMap.get("jndi-name"),
+ NO_TX_DATASOURCE));
+
+ // Make sure the entry was removed from the -ds.xml file
+ assertFalse(containsElement(propertiesMap.get("jndi-name"),
+ "no-tx-datasource"));
+ }
+
+ /**
+ * Remove an XA Datasource.
+ */
+ public void testDeleteXADatasource() throws Exception {
+ Map<String, String> propertiesMap =
createXADatasource("DeleteXADS");
+
+ deleteDatasource(propertiesMap.get("jndi-name"));
+
+ // Check for the appropriate success messages
+ String expectedMessage = "Successfully deleted XA Datasource '"
+ + propertiesMap.get("jndi-name") +
"'";
+ checkClientAndServerMessages(expectedMessage, expectedMessage, false);
+
+ assertFalse(isDatasourceDeployed(propertiesMap.get("jndi-name"),
+ XA_DATASOURCE));
+
+ // Make sure the entry was removed from the -ds.xml file
+ assertFalse(containsElement(propertiesMap.get("jndi-name"),
+ "xa-datasource"));
+ }
+
+ /*
+ * PRELIMINARY METRICS TESTS
+ */
+
+ /**
+ * Check that the metrics are correct after creating a new datasource.
+ */
+ public void testMetricsAfterDatasourceCreation() throws IOException {
+
+ // Min pool size will be 5, max pool size will be 20
+ Map<String, String> propertiesMap =
createLocalTXDatasource("MetricsCreateDS");
+
+ // Set up the expected values
+ Map<String, String> expectedMetrics = new HashMap<String, String>();
+ expectedMetrics.put("Available Connection Count", "20.0");
+ expectedMetrics.put("Connection Count", "0.0");
+ expectedMetrics.put("Connection Created Count", "0.0");
+ expectedMetrics.put("Connection Destroyed Count", "0.0");
+ expectedMetrics.put("In Use Connection Count", "0.0");
+ expectedMetrics.put("Max Connections In Use Count", "0.0");
+ expectedMetrics.put("Max Size", "20.0");
+ expectedMetrics.put("Min Size", "5.0");
+
+ checkMetrics(propertiesMap.get("jndi-name"), LOCAL_TX_DATASOURCE,
expectedMetrics);
+
+ // Clean up
+ deleteDatasource(propertiesMap.get("jndi-name"));
+ }
+
+ /**
+ * Make an initial request for a connection to a database. Make
+ * sure the metrics are updated accordingly.
+ */
+ public void testMetricsAfterInitialDBConnection() throws Exception {
+
+ // Min pool size will be 5, max pool size will be 20
+ Map<String, String> propertiesMap =
createLocalTXDatasource("MetricsInitalConnectionDS");
+
+ // Create the first connection
+ Connection con = connectDB(propertiesMap.get("jndi-name"),
"sa", "");
+ assertNotNull(con);
+
+ // Set up the expected values
+ Map<String, String> expectedMetrics = new HashMap<String, String>();
+ expectedMetrics.put("Available Connection Count", "19.0");
+ expectedMetrics.put("Connection Count", "5.0");
+ expectedMetrics.put("Connection Created Count", "5.0");
+ expectedMetrics.put("Connection Destroyed Count", "0.0");
+ expectedMetrics.put("In Use Connection Count", "1.0");
+ expectedMetrics.put("Max Connections In Use Count", "1.0");
+ expectedMetrics.put("Max Size", "20.0");
+ expectedMetrics.put("Min Size", "5.0");
+
+ checkMetrics(propertiesMap.get("jndi-name"), LOCAL_TX_DATASOURCE,
expectedMetrics);
+
+ // Clean up
+ disconnectDB(con);
+ deleteDatasource(propertiesMap.get("jndi-name"));
+ }
+
+ /**
+ * Establish multiple connections to a database. Make sure
+ * the metrics are updated accordingly.
+ */
+ public void testMetricsAfterMultipleDBConnections() throws Exception {
+
+ // Min pool size will be 5, max pool size will be 20
+ Map<String, String> propertiesMap =
createNoTXDatasource("MetricsMultipleConnectionDS");
+
+ // Establish multiple connections
+ ArrayList<Connection> connections = new ArrayList<Connection>();
+ for(int i = 0; i <= 5; i++) {
+ Connection con = connectDB(propertiesMap.get("jndi-name"),
"sa", "");
+ assertNotNull(con);
+ connections.add(con);
+ }
+
+ // Set up the expected values
+ Map<String, String> expectedMetrics = new HashMap<String, String>();
+ expectedMetrics.put("Available Connection Count", "14.0");
+ expectedMetrics.put("Connection Count", "6.0");
+ expectedMetrics.put("Connection Created Count", "6.0");
+ expectedMetrics.put("Connection Destroyed Count", "0.0");
+ expectedMetrics.put("In Use Connection Count", "6.0");
+ expectedMetrics.put("Max Connections In Use Count", "6.0");
+ expectedMetrics.put("Max Size", "20.0");
+ expectedMetrics.put("Min Size", "5.0");
+
+ checkMetrics(propertiesMap.get("jndi-name"), NO_TX_DATASOURCE,
expectedMetrics);
+
+ // Clean up
+ for(int i = 0; i <= 5; i++) {
+ disconnectDB(connections.get(i));
+ }
+
+ deleteDatasource(propertiesMap.get("jndi-name"));
+ }
}