You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2016/12/12 22:36:18 UTC

[15/46] geode git commit: GEODE-2112: Fix UITests failing due to insufficient cleanup

GEODE-2112: Fix UITests failing due to insufficient cleanup

 - Extracted setup of the Server and WebDriver for Pulse tests into JUnit Rules
 - Refactored UITests
 - Removed a lot of unused test code

This closes #287


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/190f3a21
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/190f3a21
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/190f3a21

Branch: refs/heads/feature/GEODE-1930
Commit: 190f3a217aa769de80fa981dbd0b13864be3d364
Parents: e607497
Author: Jared Stewart <js...@pivotal.io>
Authored: Thu Nov 17 14:59:20 2016 -0800
Committer: Kirk Lund <kl...@apache.org>
Committed: Fri Nov 18 09:52:51 2016 -0800

----------------------------------------------------------------------
 .../geode/management/internal/JettyHelper.java  |    3 +-
 geode-pulse/build.gradle                        |    1 +
 .../tools/pulse/testbed/driver/PulseUITest.java |  275 -----
 .../tools/pulse/tests/AggregateStatement.java   |  214 ----
 .../pulse/tests/AggregateStatementMBean.java    |  165 ---
 .../pulse/tests/DataBrowserResultLoader.java    |   25 +-
 .../pulse/tests/GemFireXDAggregateTable.java    |   42 -
 .../tests/GemFireXDAggregateTableMBean.java     |   26 -
 .../tools/pulse/tests/GemFireXDCluster.java     |   92 --
 .../pulse/tests/GemFireXDClusterMBean.java      |   30 -
 .../tools/pulse/tests/GemFireXDMember.java      |   76 --
 .../tools/pulse/tests/GemFireXDMemberMBean.java |   29 -
 .../apache/geode/tools/pulse/tests/Server.java  |   24 +-
 .../tests/rules/ScreenshotOnFailureRule.java    |   58 +
 .../tools/pulse/tests/rules/ServerRule.java     |  113 ++
 .../tools/pulse/tests/rules/WebDriverRule.java  |  122 ++
 .../tools/pulse/tests/ui/PulseAbstractTest.java | 1075 ------------------
 .../pulse/tests/ui/PulseAnonymousUserTest.java  |   96 +-
 .../tools/pulse/tests/ui/PulseAuthTest.java     |   32 +-
 .../pulse/tests/ui/PulseAutomatedTest.java      |   56 +-
 .../geode/tools/pulse/tests/ui/PulseBase.java   |  884 ++++++++++++++
 .../tools/pulse/tests/ui/PulseBaseTest.java     |  730 ------------
 .../tools/pulse/tests/ui/PulseNoAuthTest.java   |   31 +-
 .../pulse/tests/ui/PulseTestConstants.java      |   71 ++
 .../tools/pulse/tests/ui/PulseTestUtils.java    |  661 +++++++++++
 25 files changed, 2044 insertions(+), 2887 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-core/src/main/java/org/apache/geode/management/internal/JettyHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/JettyHelper.java b/geode-core/src/main/java/org/apache/geode/management/internal/JettyHelper.java
index f18aafb..7c26297 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/JettyHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/JettyHelper.java
@@ -54,8 +54,7 @@ public class JettyHelper {
 
   private static int port = 0;
 
-  public static Server initJetty(final String bindAddress, final int port, SSLConfig sslConfig)
-      throws Exception {
+  public static Server initJetty(final String bindAddress, final int port, SSLConfig sslConfig) {
 
     final Server jettyServer = new Server();
 

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/build.gradle
----------------------------------------------------------------------
diff --git a/geode-pulse/build.gradle b/geode-pulse/build.gradle
index 6692484..94f26f7 100755
--- a/geode-pulse/build.gradle
+++ b/geode-pulse/build.gradle
@@ -134,6 +134,7 @@ task uiTest(type:Test) {
     excludeCategories 'org.apache.geode.test.junit.categories.FlakyTest'
   }
 
+  forkEvery(1)
   doFirst {
     TestPropertiesWriter.writeTestProperties(buildDir, name)
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/testbed/driver/PulseUITest.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/testbed/driver/PulseUITest.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/testbed/driver/PulseUITest.java
deleted file mode 100644
index 7644006..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/testbed/driver/PulseUITest.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.tools.pulse.testbed.driver;
-
-import static org.apache.geode.tools.pulse.tests.ui.PulseAbstractTest.*;
-import static org.junit.Assert.*;
-
-import java.net.InetAddress;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.phantomjs.PhantomJSDriver;
-import org.openqa.selenium.remote.DesiredCapabilities;
-import org.openqa.selenium.support.ui.ExpectedCondition;
-import org.openqa.selenium.support.ui.WebDriverWait;
-
-import org.apache.geode.internal.admin.SSLConfig;
-import org.apache.geode.management.internal.JettyHelper;
-import org.apache.geode.test.junit.categories.UITest;
-import org.apache.geode.tools.pulse.testbed.GemFireDistributedSystem.Locator;
-import org.apache.geode.tools.pulse.testbed.GemFireDistributedSystem.Peer;
-import org.apache.geode.tools.pulse.testbed.GemFireDistributedSystem.Region;
-import org.apache.geode.tools.pulse.testbed.GemFireDistributedSystem.Server;
-import org.apache.geode.tools.pulse.testbed.TestBed;
-
-@Ignore("TODO: test is ignored")
-@Category(UITest.class)
-public class PulseUITest {
-
-  private static WebDriver driver;
-  private static TestBed testBed;
-  private static String pulseURL;
-  private static String path;
-  private static org.eclipse.jetty.server.Server jetty = null;
-
-  private static final String userName = "admin";
-  private static final String pasword = "admin";
-
-  private static final String DATA_VIEW_LABEL = "Data View";
-  private static final String CLUSTER_VIEW_MEMBERS_ID = "clusterTotalMembersText";
-  private static final String CLUSTER_VIEW_SERVERS_ID = "clusterServersText";
-  private static final String CLUSTER_VIEW_LOCATORS_ID = "clusterLocatorsText";
-  private static final String CLUSTER_VIEW_REGIONS_ID = "clusterTotalRegionsText";
-
-  @BeforeClass
-  public static void setUpJetty() throws Exception {
-    String host = InetAddress.getLocalHost().getHostAddress();
-    int port = 8080;
-    String context = "/pulse";
-    path = getPulseWarPath();
-    // System.setProperty("pulse.propMockDataUpdaterClass",
-    // "org.apache.geode.tools.pulse.testbed.PropMockDataUpdater");
-
-    jetty = JettyHelper.initJetty(host, port, new SSLConfig());
-    JettyHelper.addWebApplication(jetty, context, getPulseWarPath());
-    jetty.start();
-
-    pulseURL = "http://" + host + ":" + port + context;
-    Thread.sleep(1000); // wait till tomcat settles down
-
-    DesiredCapabilities capabilities = new DesiredCapabilities();
-    capabilities.setJavascriptEnabled(true);
-    capabilities.setCapability("takesScreenshot", true);
-    capabilities.setCapability("phantomjs.page.settings.userAgent",
-        "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0) Gecko/20121026 Firefox/16.0");
-
-    driver = new PhantomJSDriver(capabilities);
-    driver.manage().window().maximize();// required to make all elements visible
-
-    Thread.sleep(5000); // wait till pulse starts polling threads...
-    testBed = new TestBed();
-    loginToPulse(driver, userName, pasword);
-  }
-
-  @AfterClass
-  public static void stopJetty() throws Exception {
-    jetty.stop();
-  }
-
-  @After
-  public void closeSession() {
-    driver.close();
-  }
-
-  private static void loginToPulse(WebDriver driver, String userName, String password) {
-    driver.get(pulseURL);
-    WebElement userNameElement = driver.findElement(By.id("user_name"));
-    WebElement passwordElement = driver.findElement(By.id("user_password"));
-    userNameElement.sendKeys(userName);
-    passwordElement.sendKeys(password);
-    passwordElement.submit();
-    WebElement userNameOnPulsePage =
-        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
-          @Override
-          public WebElement apply(WebDriver d) {
-            return d.findElement(By.id("userName"));
-          }
-        });
-    assertNotNull(userNameOnPulsePage);
-  }
-
-
-  private void searchByLinkAndClick(String linkText) {
-    WebElement dataViewButton = By.linkText(linkText).findElement(driver);
-    assertNotNull(dataViewButton);
-    dataViewButton.click();
-  }
-
-  private void searchByIdAndClick(String id) {
-    WebElement element = driver.findElement(By.id(id));
-    assertNotNull(element);
-    element.click();
-  }
-
-  private void searchByXPathAndClick(String xpath) {
-    WebElement element = driver.findElement(By.xpath(xpath));
-    assertNotNull(element);
-    element.click();
-  }
-
-  private void waitForElementByClassName(final String className, int seconds) {
-    WebElement linkTextOnPulsePage1 =
-        (new WebDriverWait(driver, seconds)).until(new ExpectedCondition<WebElement>() {
-          @Override
-          public WebElement apply(WebDriver d) {
-            return d.findElement(By.className(className));
-          }
-        });
-    assertNotNull(linkTextOnPulsePage1);
-  }
-
-  private void waitForElementById(final String id, int seconds) {
-    WebElement element = (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
-      @Override
-      public WebElement apply(WebDriver d) {
-        return d.findElement(By.id(id));
-      }
-    });
-    assertNotNull(element);
-  }
-
-  @Test
-  public void testClusterViewTopRibbon() {
-    List<Server> servers = testBed.getRootDs().getServers();
-    List<Locator> locators = testBed.getRootDs().getLocators();
-    List<Peer> peers = testBed.getRootDs().getPeers();
-    List<Region> regions = testBed.getRootDs().getRegions();
-    int totalMembers = servers.size() + locators.size() + peers.size();
-    int clusterMembers =
-        Integer.parseInt(driver.findElement(By.id(CLUSTER_VIEW_MEMBERS_ID)).getText());
-    int clusterServers =
-        Integer.parseInt(driver.findElement(By.id(CLUSTER_VIEW_SERVERS_ID)).getText());
-    int clusterLocators =
-        Integer.parseInt(driver.findElement(By.id(CLUSTER_VIEW_LOCATORS_ID)).getText());
-    int clusterRegions =
-        Integer.parseInt(driver.findElement(By.id(CLUSTER_VIEW_REGIONS_ID)).getText());
-    assertEquals(totalMembers, clusterMembers);
-    assertEquals(servers.size(), clusterServers);
-    assertEquals(locators.size(), clusterLocators);
-    assertEquals(regions.size(), clusterRegions);
-  }
-
-
-  @Test
-  public void testDataViewRegionProperties() {
-    searchByLinkAndClick(DATA_VIEW_LABEL);
-    waitForElementByClassName("pointDetailsPadding", 10);
-    searchByIdAndClick("btngridIcon");
-
-    for (int i = 1; i < testBed.getRootDs().getRegions().size(); i++) {
-      searchByIdAndClick("" + i);
-      String regionName1 = driver.findElement(By.id("regionName")).getText();
-      @SuppressWarnings("rawtypes")
-      List regionMemberscount1 = testBed.getRootDs().getRegion(regionName1).getMembers();
-      int regionEntCount1 = testBed.getRootDs().getRegion(regionName1).getEntryCount();
-      int regionMembers1 = Integer.parseInt(driver.findElement(By.id("regionMembers")).getText());
-      int regionEntryCount1 =
-          Integer.parseInt(driver.findElement(By.id("regionEntryCount")).getText());
-      assertEquals(regionMemberscount1.size(), regionMembers1);
-      assertEquals(regionEntCount1, regionEntryCount1);
-    }
-  }
-
-
-  @Test
-  public void testMemberViewRegions() {
-
-    searchByLinkAndClick(DATA_VIEW_LABEL);
-    waitForElementByClassName("pointDetailsPadding", 10);
-    searchByXPathAndClick("//div[@title='peer1']");
-    waitForElementById("memberRegionsCount", 10);
-
-    List<Server> servers = testBed.getRootDs().getServers();
-    List<Locator> locators = testBed.getRootDs().getLocators();
-    List<Peer> peers = testBed.getRootDs().getPeers();
-
-    String prevSelectedMember = "peer1";
-
-    for (Peer p : peers) {
-      String peer = p.getName();
-      System.out.println("Checking regions mapping for member " + peer);
-      WebElement comboBox = driver.findElement(By.linkText(prevSelectedMember));
-      comboBox.click();
-      WebElement comboList = driver.findElement(By.id("clusterMembersContainer"));
-      WebElement selectedMember = comboList.findElement(By.linkText(peer));
-      selectedMember.click();
-      timeout();
-      String peername = driver.findElement(By.id("memberName")).getText();
-      List<Region> peerRegionscount = testBed.getRootDs().getRegions(peer);
-      int peerRegions = Integer.parseInt(driver.findElement(By.id("memberRegionsCount")).getText());
-      assertEquals(peerRegionscount.size(), peerRegions);
-      prevSelectedMember = peername;
-    }
-
-    for (Server s : servers) {
-      String server = s.getName();
-      System.out.println("Checking regions mapping for server " + server);
-      WebElement comboBox = driver.findElement(By.linkText(prevSelectedMember));
-      comboBox.click();
-      WebElement comboList = driver.findElement(By.id("clusterMembersContainer"));
-      WebElement selectedMember = comboList.findElement(By.linkText(server));
-      selectedMember.click();
-      timeout();
-      String peername = driver.findElement(By.id("memberName")).getText();
-      List<Region> serverRegionscount = testBed.getRootDs().getRegions(server);
-      int serverRegions =
-          Integer.parseInt(driver.findElement(By.id("memberRegionsCount")).getText());
-      assertEquals(serverRegionscount.size(), serverRegions);
-      prevSelectedMember = peername;
-    }
-    /*
-     * for (Locator l : locators) { String locator = l.getName();
-     * System.out.println("Checking regions mapping for locator " + locator); WebElement comboBox =
-     * driver.findElement(By.linkText(prevSelectedMember)); comboBox.click(); WebElement comboList =
-     * driver.findElement(By.id("clusterMembersContainer")); WebElement selectedMember =
-     * comboList.findElement(By.linkText(locator)); selectedMember.click(); timeout(); String
-     * peername = driver.findElement(By.id("memberName")).getText(); List<Region>
-     * locatorRegionscount = testBed.getRootDs().getRegions(locator); int locatorRegions =
-     * Integer.parseInt(driver.findElement( By.id("memberRegionsCount")).getText());
-     * assertIndexDetailsEquals(locatorRegionscount.size(), locatorRegions); prevSelectedMember =
-     * peername; }
-     */
-  }
-
-  public void timeout() {
-    WebElement memberNameOnPulsePage =
-        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
-          @Override
-          public WebElement apply(WebDriver d) {
-            return d.findElement(By.id("memberName"));
-          }
-        });
-    assertNotNull(memberNameOnPulsePage);
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatement.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatement.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatement.java
deleted file mode 100644
index 0c70d65..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatement.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-public class AggregateStatement extends JMXBaseBean implements AggregateStatementMBean {
-  private String name = null;
-
-  public AggregateStatement(String name) {
-    this.name = name;
-  }
-
-  protected String getKey(String propName) {
-    return "aggregatestatement." + name + "." + propName;
-  }
-
-  /**
-   * Query definition
-   * 
-   * @return
-   */
-  public String getQueryDefinition() {
-    return getString("queryDefinition");
-  }
-
-  /**
-   * Number of times this statement is compiled (including re compilations)
-   * 
-   * @return
-   */
-  @Override
-  public long getNumTimesCompiled() {
-    return getLong("numTimesCompiled");
-  }
-
-  /**
-   * Number of times this statement is executed
-   * 
-   * @return
-   */
-  @Override
-  public long getNumExecution() {
-    return getLong("numExecution");
-  }
-
-  /**
-   * Statements that are actively being processed during the statistics snapshot
-   * 
-   * @return
-   */
-  public long getNumExecutionsInProgress() {
-    return getLong("numExecutionsInProgress");
-  }
-
-  /**
-   * Number of times global index lookup message exchanges occurred
-   * 
-   * @return
-   */
-  public long getNumTimesGlobalIndexLookup() {
-    return getLong("numTimesGlobalIndexLookup");
-  }
-
-  /**
-   * Number of rows modified by DML operation of insert/delete/update
-   * 
-   * @return
-   */
-  public long getNumRowsModified() {
-    return getLong("numRowsModified");
-  }
-
-  /**
-   * Time spent(in milliseconds) in parsing the query string
-   * 
-   * @return
-   */
-  public long getParseTime() {
-    return getLong("parseTime");
-  }
-
-  /**
-   * Time spent (in milliseconds) mapping this statement with database object's metadata (bind)
-   * 
-   * @return
-   */
-  public long getBindTime() {
-    return getLong("bindTime");
-  }
-
-  /**
-   * Time spent (in milliseconds) determining the best execution path for this statement (optimize)
-   * 
-   * @return
-   */
-  public long getOptimizeTime() {
-    return getLong("optimizeTime");
-  }
-
-  /**
-   * Time spent (in milliseconds) compiling details about routing information of query strings to
-   * data node(s) (processQueryInfo)
-   * 
-   * @return
-   */
-  public long getRoutingInfoTime() {
-    return getLong("routingInfoTime");
-  }
-
-  /**
-   * Time spent (in milliseconds) to generate query execution plan definition (activation class)
-   * 
-   * @return
-   */
-  public long getGenerateTime() {
-    return getLong("generateTime");
-  }
-
-  /**
-   * Total compilation time (in milliseconds) of the statement on this node (prepMinion)
-   * 
-   * @return
-   */
-  public long getTotalCompilationTime() {
-    return getLong("totalCompilationTime");
-  }
-
-  /**
-   * Time spent (in nanoseconds) in creation of all the layers of query processing (ac.execute)
-   * 
-   * @return
-   */
-  public long getExecutionTime() {
-    return getLong("executionTime");
-  }
-
-  /**
-   * Time to apply (in nanoseconds) the projection and additional filters. (projectrestrict)
-   * 
-   * @return
-   */
-  public long getProjectionTime() {
-    return getLong("projectionTime");
-  }
-
-  /**
-   * Total execution time (in nanoseconds) taken to process the statement on this node
-   * (execute/open/next/close)
-   * 
-   * @return
-   */
-  public long getTotalExecutionTime() {
-    return getLong("totalExecutionTime");
-  }
-
-  /**
-   * Time taken (in nanoseconds) to modify rows by DML operation of insert/delete/update
-   * 
-   * @return
-   */
-  public long getRowsModificationTime() {
-    return getLong("rowsModificationTime");
-  }
-
-  /**
-   * Number of rows returned from remote nodes (ResultHolder/Get convertibles)
-   * 
-   * @return
-   */
-  public long getQNNumRowsSeen() {
-    return getLong("qnNumRowsSeen");
-  }
-
-  /**
-   * TCP send time (in nanoseconds) of all the messages including serialization time and queue wait
-   * time
-   * 
-   * @return
-   */
-  public long getQNMsgSendTime() {
-    return getLong("qnMsgSendTime");
-  }
-
-  /**
-   * Serialization time (in nanoseconds) for all the messages while sending to remote node(s)
-   * 
-   * @return
-   */
-  public long getQNMsgSerTime() {
-    return getLong("qnMsgSerTime");
-  }
-
-  /**
-   * 
-   * 
-   * @return
-   */
-  public long getQNRespDeSerTime() {
-    return getLong("qnRespDeSerTime");
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatementMBean.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatementMBean.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatementMBean.java
deleted file mode 100644
index 8efb699..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/AggregateStatementMBean.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-public interface AggregateStatementMBean {
-  String OBJECT_NAME = "GemFireXD:service=Statement,type=Aggregate";
-
-  /**
-   * Query definition
-   *
-   * @return
-   */
-  String getQueryDefinition();
-
-  /**
-   * Number of times this statement is compiled (including re compilations)
-   *
-   * @return
-   */
-  long getNumTimesCompiled();
-
-  /**
-   * Number of times this statement is executed
-   *
-   * @return
-   */
-  long getNumExecution();
-
-  /**
-   * Statements that are actively being processed during the statistics snapshot
-   *
-   * @return
-   */
-  long getNumExecutionsInProgress();
-
-  /**
-   * Number of times global index lookup message exchanges occurred
-   *
-   * @return
-   */
-  long getNumTimesGlobalIndexLookup();
-
-  /**
-   * Number of rows modified by DML operation of insert/delete/update
-   *
-   * @return
-   */
-  long getNumRowsModified();
-
-  /**
-   * Time spent(in milliseconds) in parsing the query string
-   *
-   * @return
-   */
-  long getParseTime();
-
-  /**
-   * Time spent (in milliseconds) mapping this statement with database object's metadata (bind)
-   *
-   * @return
-   */
-  long getBindTime();
-
-  /**
-   * Time spent (in milliseconds) determining the best execution path for this statement (optimize)
-   *
-   * @return
-   */
-  long getOptimizeTime();
-
-  /**
-   * Time spent (in milliseconds) compiling details about routing information of query strings to
-   * data node(s) (processQueryInfo)
-   *
-   * @return
-   */
-  long getRoutingInfoTime();
-
-  /**
-   * Time spent (in milliseconds) to generate query execution plan definition (activation class)
-   *
-   * @return
-   */
-  long getGenerateTime();
-
-  /**
-   * Total compilation time (in milliseconds) of the statement on this node (prepMinion)
-   *
-   * @return
-   */
-  long getTotalCompilationTime();
-
-  /**
-   * Time spent (in nanoseconds) in creation of all the layers of query processing (ac.execute)
-   *
-   * @return
-   */
-  long getExecutionTime();
-
-  /**
-   * Time to apply (in nanoseconds) the projection and additional filters. (projectrestrict)
-   *
-   * @return
-   */
-  long getProjectionTime();
-
-  /**
-   * Total execution time (in nanoseconds) taken to process the statement on this node
-   * (execute/open/next/close)
-   *
-   * @return
-   */
-  long getTotalExecutionTime();
-
-  /**
-   * Time taken (in nanoseconds) to modify rows by DML operation of insert/delete/update
-   *
-   * @return
-   */
-  long getRowsModificationTime();
-
-  /**
-   * Number of rows returned from remote nodes (ResultHolder/Get convertibles)
-   *
-   * @return
-   */
-  long getQNNumRowsSeen();
-
-  /**
-   * TCP send time (in nanoseconds) of all the messages including serialization time and queue wait
-   * time
-   *
-   * @return
-   */
-  long getQNMsgSendTime();
-
-  /**
-   * Serialization time (in nanoseconds) for all the messages while sending to remote node(s)
-   *
-   * @return
-   */
-  long getQNMsgSerTime();
-
-  /**
-   *
-   *
-   * @return
-   */
-  long getQNRespDeSerTime();
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/DataBrowserResultLoader.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/DataBrowserResultLoader.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/DataBrowserResultLoader.java
index f473f11..6c50fbc 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/DataBrowserResultLoader.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/DataBrowserResultLoader.java
@@ -24,9 +24,16 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
 
-import org.apache.geode.tools.pulse.tests.ui.PulseAbstractTest;
-
 public class DataBrowserResultLoader {
+  /* Constants for executing Data Browser queries */
+  public static final String QUERY_TYPE_ONE = "query1";
+  public static final String QUERY_TYPE_TWO = "query2";
+  public static final String QUERY_TYPE_THREE = "query3";
+  public static final String QUERY_TYPE_FOUR = "query4";
+  public static final String QUERY_TYPE_FIVE = "query5";
+  public static final String QUERY_TYPE_SIX = "query6";
+  public static final String QUERY_TYPE_SEVENE = "query7";
+
   private static DataBrowserResultLoader dbResultLoader = new DataBrowserResultLoader();
 
   public static DataBrowserResultLoader getInstance() {
@@ -44,19 +51,19 @@ public class DataBrowserResultLoader {
     try {
       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 
-      if (queryString.equals(PulseAbstractTest.QUERY_TYPE_ONE)) {
+      if (queryString.equals(QUERY_TYPE_ONE)) {
         url = classLoader.getResource("testQueryResultClusterSmall.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_TWO)) {
+      } else if (queryString.equals(QUERY_TYPE_TWO)) {
         url = classLoader.getResource("testQueryResultSmall.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_THREE)) {
+      } else if (queryString.equals(QUERY_TYPE_THREE)) {
         url = classLoader.getResource("testQueryResult.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_FOUR)) {
+      } else if (queryString.equals(QUERY_TYPE_FOUR)) {
         url = classLoader.getResource("testQueryResultWithStructSmall.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_FIVE)) {
+      } else if (queryString.equals(QUERY_TYPE_FIVE)) {
         url = classLoader.getResource("testQueryResultClusterWithStruct.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_SIX)) {
+      } else if (queryString.equals(QUERY_TYPE_SIX)) {
         url = classLoader.getResource("testQueryResultHashMapSmall.txt");
-      } else if (queryString.equals(PulseAbstractTest.QUERY_TYPE_SEVENE)) {
+      } else if (queryString.equals(QUERY_TYPE_SEVENE)) {
         url = classLoader.getResource("testQueryResult1000.txt");
       } else {
         url = classLoader.getResource("testQueryResult.txt");

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTable.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTable.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTable.java
deleted file mode 100644
index 84c03cb..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTable.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-import javax.management.NotificationBroadcasterSupport;
-
-public class GemFireXDAggregateTable extends NotificationBroadcasterSupport
-    implements GemFireXDAggregateTableMBean {
-  private String name = null;
-
-  public GemFireXDAggregateTable(String name) {
-    this.name = name;
-  }
-
-  private String getKey(String propName) {
-    return "table." + name + "." + propName;
-  }
-
-  @Override
-  public long getEntrySize() {
-    return Long.parseLong(JMXProperties.getInstance().getProperty(getKey("EntrySize")));
-  }
-
-  @Override
-  public int getNumberOfRows() {
-    return Integer.parseInt(JMXProperties.getInstance().getProperty(getKey("NumberOfRows")));
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTableMBean.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTableMBean.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTableMBean.java
deleted file mode 100644
index f99c657..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDAggregateTableMBean.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-public interface GemFireXDAggregateTableMBean {
-  public static final String OBJECT_NAME = "GemFireXD:service=Table,type=Aggregate,table=";
-
-  public long getEntrySize();
-
-  public int getNumberOfRows();
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDCluster.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDCluster.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDCluster.java
deleted file mode 100644
index 5afe935..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDCluster.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-public class GemFireXDCluster extends NotificationBroadcasterSupport
-    implements GemFireXDClusterMBean {
-  private String name = null;
-
-  private static String[] itemNames =
-      {"connectionsAttempted", "connectionsActive", "connectionsClosed", "connectionsFailed"};;
-  private static String[] itemDescriptions =
-      {"connectionsAttempted", "connectionsActive", "connectionsClosed", "connectionsFailed"};
-  private static OpenType[] itemTypes =
-      {SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG};
-  private static CompositeType networkServerClientConnectionStats = null;
-
-  static {
-    try {
-      networkServerClientConnectionStats = new CompositeType("NetworkServerClientConnectionStats",
-          "Network Server Client Connection Stats Information", itemNames, itemDescriptions,
-          itemTypes);
-
-    } catch (OpenDataException e) {
-      e.printStackTrace();
-    }
-  }
-
-  public GemFireXDCluster(String name) {
-    this.name = name;
-  }
-
-  private String getKey(String propName) {
-    return "gemfirexd." + name + "." + propName;
-  }
-
-  @Override
-  public int getProcedureCallsCompleted() {
-    return Integer
-        .parseInt(JMXProperties.getInstance().getProperty(getKey("ProcedureCallsCompleted")));
-  }
-
-  @Override
-  public int getProcedureCallsInProgress() {
-    return Integer
-        .parseInt(JMXProperties.getInstance().getProperty(getKey("ProcedureCallsInProgress")));
-  }
-
-  @Override
-  public CompositeData getNetworkServerClientConnectionStats() {
-    String value =
-        JMXProperties.getInstance().getProperty(getKey("NetworkServerClientConnectionStats"), "");
-    String[] values = value.split(",");
-    Long[] itemValues = new Long[values.length];
-    for (int i = 0; i < values.length; i++) {
-      itemValues[i] = Long.parseLong(values[i]);
-    }
-
-    CompositeData nscCompData;
-    try {
-      nscCompData =
-          new CompositeDataSupport(networkServerClientConnectionStats, itemNames, itemValues);
-    } catch (OpenDataException e) {
-      e.printStackTrace();
-      nscCompData = null;
-    }
-    return nscCompData;
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDClusterMBean.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDClusterMBean.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDClusterMBean.java
deleted file mode 100644
index f42ace4..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDClusterMBean.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-import javax.management.openmbean.CompositeData;
-
-public interface GemFireXDClusterMBean {
-  public static final String OBJECT_NAME = "GemFireXD:service=Cluster";
-
-  public int getProcedureCallsCompleted();
-
-  public int getProcedureCallsInProgress();
-
-  public CompositeData getNetworkServerClientConnectionStats();
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMember.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMember.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMember.java
deleted file mode 100644
index 5603732..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMember.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-public class GemFireXDMember extends JMXBaseBean implements GemFireXDMemberMBean {
-  private String name = null;
-
-  private static String[] itemNames =
-      {"connectionsAttempted", "connectionsActive", "connectionsClosed", "connectionsFailed"};;
-  private static String[] itemDescriptions =
-      {"connectionsAttempted", "connectionsActive", "connectionsClosed", "connectionsFailed"};
-  private static OpenType[] itemTypes =
-      {SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG};
-  private static CompositeType networkServerClientConnectionStats = null;
-
-  static {
-    try {
-      networkServerClientConnectionStats = new CompositeType("NetworkServerClientConnectionStats",
-          "Network Server Client Connection Stats Information", itemNames, itemDescriptions,
-          itemTypes);
-
-    } catch (OpenDataException e) {
-      e.printStackTrace();
-    }
-  }
-
-  public GemFireXDMember(String name) {
-    this.name = name;
-  }
-
-  @Override
-  protected String getKey(String propName) {
-    return "gemfirexdmember." + name + "." + propName;
-  }
-
-  @Override
-  public boolean getDataStore() {
-    return getBoolean("DataStore");
-  }
-
-  @Override
-  public CompositeData getNetworkServerClientConnectionStats() {
-    Long[] itemValues = getLongArray("NetworkServerClientConnectionStats");
-    CompositeData nscCompData;
-    try {
-      nscCompData =
-          new CompositeDataSupport(networkServerClientConnectionStats, itemNames, itemValues);
-    } catch (OpenDataException e) {
-      e.printStackTrace();
-      nscCompData = null;
-    }
-    return nscCompData;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMemberMBean.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMemberMBean.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMemberMBean.java
deleted file mode 100644
index 76b5c51..0000000
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/GemFireXDMemberMBean.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- *
- */
-package org.apache.geode.tools.pulse.tests;
-
-import javax.management.openmbean.CompositeData;
-
-public interface GemFireXDMemberMBean {
-
-  public static final String OBJECT_NAME = "GemFireXD:group=DEFAULT,type=Member";
-
-  public boolean getDataStore();
-
-  public CompositeData getNetworkServerClientConnectionStats();
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/Server.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/Server.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/Server.java
index 4dd3126..10ef440 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/Server.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/Server.java
@@ -123,12 +123,8 @@ public class Server {
     return jmxSerURL;
   }
 
-  public void stop() {
-    try {
-      cs.stop();
-    } catch (IOException e) {
-      e.printStackTrace();
-    }
+  public void stop() throws IOException {
+    cs.stop();
   }
 
   private synchronized void loadMBeans() {
@@ -194,21 +190,12 @@ public class Server {
     }
   }
 
-  private void addMemberMBean(String m)
-      throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException,
-      MalformedObjectNameException, NullPointerException {
+  private void addMemberMBean(String m) throws InstanceAlreadyExistsException,
+      MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException {
     Member m1 = new Member(m);
     mbs.registerMBean(m1, new ObjectName(Member.OBJECT_NAME + ",member=" + m));
   }
 
-  // For GemFire XD
-  private void addGemFireXDMemberMBean(String xdm)
-      throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException,
-      MalformedObjectNameException, NullPointerException {
-    GemFireXDMember xdmo = new GemFireXDMember(xdm);
-    mbs.registerMBean(xdmo, new ObjectName(GemFireXDMember.OBJECT_NAME + ",member=" + xdm));
-  }
-
   private void addRegionMBean(String reg)
       throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException,
       MalformedObjectNameException, NullPointerException {
@@ -236,8 +223,7 @@ public class Server {
     return propVal.split(" ");
   }
 
-  public static Server createServer(int port, String properties, String jsonAuthFile)
-      throws MalformedObjectNameException {
+  public static Server createServer(int port, String properties, String jsonAuthFile) {
     Server s = null;
     try {
       s = new Server(port, properties, jsonAuthFile);

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ScreenshotOnFailureRule.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ScreenshotOnFailureRule.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ScreenshotOnFailureRule.java
new file mode 100644
index 0000000..1b234b7
--- /dev/null
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ScreenshotOnFailureRule.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ */
+
+package org.apache.geode.tools.pulse.tests.rules;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.openqa.selenium.OutputType;
+import org.openqa.selenium.TakesScreenshot;
+import org.openqa.selenium.WebDriver;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.function.Supplier;
+
+public class ScreenshotOnFailureRule extends TestWatcher {
+
+  private Supplier<WebDriver> webDriverSupplier;
+
+  public ScreenshotOnFailureRule(final Supplier<WebDriver> provider) {
+    this.webDriverSupplier = provider;
+  }
+
+  @Override
+  public void failed(Throwable t, Description test) {
+    takeScreenshot(test.getDisplayName());
+  }
+
+  private void takeScreenshot(String screenshotName) {
+    WebDriver driver = this.webDriverSupplier.get();
+    if (driver instanceof TakesScreenshot) {
+      File tempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
+      try {
+        FileUtils.copyFile(tempFile, new File("build/screenshots/" + screenshotName + ".png"));
+      } catch (IOException e) {
+        throw new Error(e);
+      }
+    }
+  }
+
+
+
+}
+

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ServerRule.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ServerRule.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ServerRule.java
new file mode 100644
index 0000000..308489c
--- /dev/null
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/ServerRule.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ */
+
+package org.apache.geode.tools.pulse.tests.rules;
+
+
+import com.jayway.awaitility.Awaitility;
+import org.apache.geode.internal.AvailablePort;
+import org.apache.geode.internal.admin.SSLConfig;
+import org.apache.geode.management.internal.JettyHelper;
+import org.apache.geode.tools.pulse.tests.Server;
+
+import org.junit.rules.ExternalResource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+public class ServerRule extends ExternalResource {
+  public static final String LOCALHOST = "localhost";
+  public static final String PULSE_CONTEXT = "/pulse";
+
+  private org.eclipse.jetty.server.Server jetty;
+  private Server server;
+  private String pulseURL;
+
+  public ServerRule(String jsonAuthFile) {
+    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    String jmxPropertiesFile = classLoader.getResource("test.properties").getPath();
+    server = Server.createServer(9999, jmxPropertiesFile, jsonAuthFile);
+
+    int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
+
+    jetty = JettyHelper.initJetty(LOCALHOST, port, new SSLConfig());
+    JettyHelper.addWebApplication(jetty, PULSE_CONTEXT, getPulseWarPath());
+    pulseURL = "http://" + LOCALHOST + ":" + port + PULSE_CONTEXT;
+    System.out.println("Pulse started at " + pulseURL);
+
+  }
+
+  public String getPulseURL() {
+    return this.pulseURL;
+  }
+
+
+  @Override
+  protected void before() throws Throwable {
+    jetty.start();
+    Awaitility.await().until(() -> jetty.isStarted());
+  }
+
+  @Override
+  protected void after() {
+    try {
+      stopJetty();
+    } finally {
+      stopServer();
+    }
+  }
+
+  private void stopServer() {
+    try {
+      if (server != null) {
+        server.stop();
+      }
+    } catch (Exception e) {
+      throw new Error(e);
+    }
+  }
+
+  private void stopJetty() {
+    try {
+      if (jetty != null) {
+        jetty.stop();
+        jetty = null;
+      }
+    } catch (Exception e) {
+      throw new Error(e);
+    }
+  }
+
+  private String getPulseWarPath() {
+    String warPath = null;
+    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    InputStream inputStream = classLoader.getResourceAsStream("GemFireVersion.properties");
+    Properties properties = new Properties();
+    try {
+      properties.load(inputStream);
+    } catch (IOException e) {
+      throw new RuntimeException("Unable to open properties file", e);
+    }
+    String version = properties.getProperty("Product-Version");
+    warPath = "geode-pulse-" + version + ".war";
+    String propFilePath = classLoader.getResource("GemFireVersion.properties").getPath();
+    warPath =
+        propFilePath.substring(0, propFilePath.indexOf("generated-resources")) + "libs/" + warPath;
+    return warPath;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/190f3a21/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/WebDriverRule.java
----------------------------------------------------------------------
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/WebDriverRule.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/WebDriverRule.java
new file mode 100644
index 0000000..b4fc6b8
--- /dev/null
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/tests/rules/WebDriverRule.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ */
+
+package org.apache.geode.tools.pulse.tests.rules;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Rule;
+import org.junit.rules.ExternalResource;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.phantomjs.PhantomJSDriver;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.util.concurrent.TimeUnit;
+
+public class WebDriverRule extends ExternalResource {
+  private WebDriver driver;
+
+  private String pulseUrl;
+  private String username;
+  private String password;
+
+  public WebDriverRule(String pulseUrl) {
+    this.pulseUrl = pulseUrl;
+  }
+
+  public WebDriverRule(String username, String password, String pulseUrl) {
+    this.username = username;
+    this.password = password;
+    this.pulseUrl = pulseUrl;
+  }
+
+  public WebDriver getDriver() {
+    return this.driver;
+  }
+
+  @Rule
+  public ScreenshotOnFailureRule screenshotOnFailureRule =
+      new ScreenshotOnFailureRule(() -> driver);
+
+  public String getPulseURL() {
+    return pulseUrl;
+  }
+
+
+  @Override
+  protected void before() throws Throwable {
+    if (driver == null) {
+      setUpWebDriver();
+    }
+    driver.get(getPulseURL());
+    if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
+      login();
+    }
+    driver.navigate().refresh();
+  }
+
+  @Override
+  protected void after() {
+    driver.close();
+  }
+
+  private void login() {
+    WebElement userNameElement = waitForElementById("user_name");
+    WebElement passwordElement = waitForElementById("user_password");
+    userNameElement.sendKeys(username);
+    passwordElement.sendKeys(password);
+    passwordElement.submit();
+
+    driver.get(getPulseURL() + "/clusterDetail.html");
+    WebElement userNameOnPulsePage =
+        (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
+          @Override
+          public WebElement apply(WebDriver d) {
+            return d.findElement(By.id("userName"));
+          }
+        });
+    assertNotNull(userNameOnPulsePage);
+  }
+
+  private void setUpWebDriver() {
+    DesiredCapabilities capabilities = new DesiredCapabilities();
+    capabilities.setJavascriptEnabled(true);
+    capabilities.setCapability("takesScreenshot", true);
+    capabilities.setCapability("phantomjs.page.settings.userAgent",
+        "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0) Gecko/20121026 Firefox/16.0");
+
+    driver = new PhantomJSDriver(capabilities);
+    driver.manage().window().maximize();
+    driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
+    driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
+  }
+
+  public WebElement waitForElementById(final String id) {
+    WebElement element = (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
+      @Override
+      public WebElement apply(WebDriver d) {
+        return d.findElement(By.id(id));
+      }
+    });
+    assertNotNull(element);
+    return element;
+  }
+}