Repository: ambari Updated Branches: refs/heads/trunk 8dae74cc2 -> 3153b9bc2
AMBARI-20955. Integrate Log Search integration test framework with Selenium (oleewere) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3153b9bc Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3153b9bc Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3153b9bc Branch: refs/heads/trunk Commit: 3153b9bc2f3ea9b3330e84aa34c34fc9457f01ad Parents: 8dae74c Author: oleewere <oleew...@gmail.com> Authored: Mon May 8 16:31:22 2017 +0200 Committer: oleewere <oleew...@gmail.com> Committed: Tue May 9 14:05:50 2017 +0200 ---------------------------------------------------------------------- ambari-logsearch/README.md | 8 +- ambari-logsearch/ambari-logsearch-it/pom.xml | 173 ++++++++++++--- .../logsearch/domain/StoryDataRegistry.java | 10 + .../logsearch/steps/AbstractLogSearchSteps.java | 162 ++++++++++++++ .../logsearch/steps/LogSearchDockerSteps.java | 116 +--------- .../logsearch/steps/LogSearchUISteps.java | 212 +++++++++++++++++++ .../logsearch/story/LogSearchApiQueryStory.java | 22 -- .../story/LogSearchBackendStories.java | 84 ++++++++ .../ambari/logsearch/story/LogSearchStory.java | 60 ------ .../logsearch/story/LogSearchUIStories.java | 93 ++++++++ .../logsearch/story/LogfeederParsingStory.java | 22 -- .../ambari/logsearch/web/AbstractPage.java | 63 ++++++ .../org/apache/ambari/logsearch/web/Home.java | 39 ++++ .../story/log_search_api_query_story.story | 17 -- .../story/logfeeder_parsing_story.story | 20 -- .../backend/log_search_api_query_story.story | 17 ++ .../backend/logfeeder_parsing_story.story | 20 ++ .../resources/stories/selenium/login.ui.story | 20 ++ ambari-logsearch/docker/Dockerfile | 17 +- ambari-logsearch/docker/bin/start.sh | 8 + ambari-logsearch/docker/logsearch-docker.sh | 10 +- 21 files changed, 901 insertions(+), 292 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/README.md ---------------------------------------------------------------------- diff --git a/ambari-logsearch/README.md b/ambari-logsearch/README.md index 5c41fcd..4123a52 100644 --- a/ambari-logsearch/README.md +++ b/ambari-logsearch/README.md @@ -36,10 +36,14 @@ mvn -Dbuild-deb clean package ## Running Integration Tests -By default integration tests are not a part of the build process, you need to set ${it.skip} variable to true (docker needed here too) +By default integration tests are not a part of the build process, you need to set -Dbackend-tests or -Dselenium-tests (or you can use -Dall-tests to run both). To running the tests you will need docker here as well (right now docker-for-mac and unix are supported only). ```bash # from ambari-logsearch folder -mvn clean integration-test -Dit.skip=false +mvn clean integration-test -Dbackend-tests failsafe:verify +# or run selenium tests with docker for mac, but before that you nedd to start xquartz +xquartz +# then in an another window you can start ui tests +mvn clean integration-test -Dselenium-tests failsafe:verify ``` Also you can run from the IDE, but make sure all of the ambari logsearch modules are built. http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/pom.xml ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/pom.xml b/ambari-logsearch/ambari-logsearch-it/pom.xml index ee97e99..cdb76a5 100644 --- a/ambari-logsearch/ambari-logsearch-it/pom.xml +++ b/ambari-logsearch/ambari-logsearch-it/pom.xml @@ -33,8 +33,10 @@ <properties> <it.skip>true</it.skip> <jbehave.version>4.0.5</jbehave.version> + <jbehave-selenium>3.5.5</jbehave-selenium> <jersey.version>2.23.1</jersey.version> <jackson-jaxrs.version>2.6.4</jackson-jaxrs.version> + <failsafe-plugin.version>2.20</failsafe-plugin.version> <forkCount>1</forkCount> </properties> @@ -45,6 +47,11 @@ <version>${jbehave.version}</version> </dependency> <dependency> + <groupId>org.jbehave.web</groupId> + <artifactId>jbehave-web-selenium</artifactId> + <version>${jbehave-selenium}</version> + </dependency> + <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>${solr.version}</version> @@ -82,6 +89,12 @@ <groupId>com.flipkart.zjsonpatch</groupId> <artifactId>zjsonpatch</artifactId> <version>0.2.4</version> + <exclusions> + <exclusion> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.apache.ambari</groupId> @@ -98,6 +111,11 @@ <artifactId>ambari-logsearch-logfeeder</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>11.0.1</version> + </dependency> </dependencies> <build> @@ -113,35 +131,132 @@ <directory>src/test/resources</directory> </testResource> </testResources> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - <executions> - <execution> - <id>run-integration-tests</id> - <phase>integration-test</phase> - <goals> - <goal>integration-test</goal> - </goals> - <configuration> - <includes> - <include>**/*Stories.java</include> - <include>**/*Story.java</include> - </includes> - <skip>${it.skip}</skip> - </configuration> - </execution> - <execution> - <id>verify-integration-tests</id> - <phase>verify</phase> - <goals> - <goal>verify</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> </build> + <profiles> + <profile> + <id>selenium-tests</id> + <activation> + <property> + <name>selenium-tests</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${failsafe-plugin.version}</version> + <executions> + <execution> + <id>run-integration-tests</id> + <phase>integration-test</phase> + <goals> + <goal>integration-test</goal> + </goals> + <configuration> + <includes> + <include>**/*UIStories.java</include> + </includes> + <systemPropertyVariables> + <log4j.configuration>file:${project.build.testOutputDirectory}/log4j.properties</log4j.configuration> + </systemPropertyVariables> + </configuration> + </execution> + <execution> + <id>verify-integration-tests</id> + <phase>verify</phase> + <goals> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>backend-tests</id> + <activation> + <property> + <name>backend-tests</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${failsafe-plugin.version}</version> + <executions> + <execution> + <id>run-integration-tests</id> + <phase>integration-test</phase> + <goals> + <goal>integration-test</goal> + </goals> + <configuration> + <includes> + <include>**/*BackendStories.java</include> + </includes> + <systemPropertyVariables> + <log4j.configuration>file:${project.build.testOutputDirectory}/log4j.properties</log4j.configuration> + </systemPropertyVariables> + </configuration> + </execution> + <execution> + <id>verify-integration-tests</id> + <phase>verify</phase> + <goals> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>all-tests</id> + <activation> + <property> + <name>all-tests</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${failsafe-plugin.version}</version> + <executions> + <execution> + <id>run-integration-tests</id> + <phase>integration-test</phase> + <goals> + <goal>integration-test</goal> + </goals> + <configuration> + <includes> + <include>**/*Stories.java</include> + </includes> + <systemPropertyVariables> + <log4j.configuration>file:${project.build.testOutputDirectory}/log4j.properties</log4j.configuration> + </systemPropertyVariables> + </configuration> + </execution> + <execution> + <id>verify-integration-tests</id> + <phase>verify</phase> + <goals> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + </project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/domain/StoryDataRegistry.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/domain/StoryDataRegistry.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/domain/StoryDataRegistry.java index cb72376..41d6391 100644 --- a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/domain/StoryDataRegistry.java +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/domain/StoryDataRegistry.java @@ -19,6 +19,7 @@ package org.apache.ambari.logsearch.domain; import org.apache.solr.client.solrj.SolrClient; +import org.jbehave.web.selenium.WebDriverProvider; public class StoryDataRegistry { public static final StoryDataRegistry INSTANCE = new StoryDataRegistry(); @@ -33,6 +34,7 @@ public class StoryDataRegistry { private final int zookeeperPort = 9983; private final String serviceLogsCollection = "hadoop_logs"; private final String auditLogsCollection = "audit_logs"; + private WebDriverProvider webDriverProvider; private StoryDataRegistry() { } @@ -96,4 +98,12 @@ public class StoryDataRegistry { public void setLogsearchContainerStarted(boolean logsearchContainerStarted) { this.logsearchContainerStarted = logsearchContainerStarted; } + + public WebDriverProvider getWebDriverProvider() { + return webDriverProvider; + } + + public void setWebDriverProvider(WebDriverProvider webDriverProvider) { + this.webDriverProvider = webDriverProvider; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/AbstractLogSearchSteps.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/AbstractLogSearchSteps.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/AbstractLogSearchSteps.java new file mode 100644 index 0000000..a7dd409 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/AbstractLogSearchSteps.java @@ -0,0 +1,162 @@ +/* + * 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.ambari.logsearch.steps; + +import org.apache.ambari.logsearch.domain.StoryDataRegistry; +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.LBHttpSolrClient; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.client.solrj.response.SolrPingResponse; +import org.apache.solr.common.SolrDocumentList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URL; + +public class AbstractLogSearchSteps { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractLogSearchSteps.class); + + protected void initDockerContainer() throws Exception{ + boolean logsearchStarted = StoryDataRegistry.INSTANCE.isLogsearchContainerStarted(); + if (!logsearchStarted) { + LOG.info("Create new docker container for Log Search ..."); + URL location = LogSearchDockerSteps.class.getProtectionDomain().getCodeSource().getLocation(); + String ambariFolder = new File(location.toURI()).getParentFile().getParentFile().getParentFile().getParent(); + StoryDataRegistry.INSTANCE.setAmbariFolder(ambariFolder); + String shellScriptLocation = ambariFolder + "/ambari-logsearch/docker/logsearch-docker.sh"; + StoryDataRegistry.INSTANCE.setShellScriptLocation(shellScriptLocation); + String output = runCommand(new String[]{StoryDataRegistry.INSTANCE.getShellScriptLocation(), "start"}); + LOG.info("Command output: {}", output); + StoryDataRegistry.INSTANCE.setLogsearchContainerStarted(true); + + // TODO: create a script which returns the proper host for docker, use: runCommand or an env variable + String dockerHostFromUri = "localhost"; + + StoryDataRegistry.INSTANCE.setDockerHost(dockerHostFromUri); + checkHostAndPortReachable(dockerHostFromUri, StoryDataRegistry.INSTANCE.getLogsearchPort(), "LogSearch"); + waitUntilSolrIsUp(); + waitUntilSolrHasAnyData(); + + LOG.info("Waiting for logfeeder to finish the test log parsings... (10 sec)"); + Thread.sleep(10000); + } + } + + private void waitUntilSolrIsUp() throws Exception { + int maxTries = 30; + boolean solrIsUp = false; + String lastExceptionMessage = null; + for (int tries = 1; tries < maxTries; tries++) { + try { + SolrClient solrClient = new LBHttpSolrClient(String.format("http://%s:%d/solr/%s_shard0_replica1", + StoryDataRegistry.INSTANCE.getDockerHost(), + StoryDataRegistry.INSTANCE.getSolrPort(), + StoryDataRegistry.INSTANCE.getServiceLogsCollection())); + StoryDataRegistry.INSTANCE.setSolrClient(solrClient); + SolrPingResponse pingResponse = solrClient.ping(); + if (pingResponse.getStatus() != 0) { + LOG.info("Solr is not up yet, Retrying... ({} tries)", tries); + Thread.sleep(2000); + } else { + solrIsUp = true; + LOG.info("Solr is up and running"); + break; + } + } catch (Exception e) { + LOG.info("Error occurred during pinging solr. Retrying... ({} tries)", tries); + lastExceptionMessage = e.getMessage(); + Thread.sleep(2000); + } + } + + if (!solrIsUp) { + throw new IllegalStateException(String.format("Solr is not up after %d tries. Exception: %s", maxTries, lastExceptionMessage)); + } + } + + protected void waitUntilSolrHasAnyData() throws IOException, SolrServerException, InterruptedException { + boolean solrHasData = false; + int maxTries = 60; + String lastExceptionMessage = null; + for (int tries = 1; tries < maxTries; tries++) { + try { + SolrClient solrClient = StoryDataRegistry.INSTANCE.getSolrClient(); + SolrQuery solrQuery = new SolrQuery(); + solrQuery.setQuery("*:*"); + QueryResponse queryResponse = solrClient.query(solrQuery); + SolrDocumentList list = queryResponse.getResults(); + if (list.size() > 0) { + solrHasData = true; + break; + } else { + Thread.sleep(2000); + LOG.info("Solr has no data yet. Retrying... ({} tries)", tries); + } + } catch (Exception e) { + LOG.info("Error occurred during checking solr. Retrying... ({} tries)", tries); + lastExceptionMessage = e.getMessage(); + Thread.sleep(2000); + } + } + if (!solrHasData) { + throw new IllegalStateException(String.format("Solr has no data after %d tries. Exception: %s", maxTries, lastExceptionMessage)); + } + } + + + protected void checkHostAndPortReachable(String host, int port, String serviceName) throws InterruptedException { + boolean reachable = false; + int maxTries = 60; + for (int tries = 1; tries < maxTries; tries++ ) { + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(host, port), 1000); + reachable = true; + break; + } catch (IOException e) { + Thread.sleep(2000); + LOG.info("{} is not reachable yet. Retrying... ({} tries)", serviceName, tries); + } + } + if (!reachable) { + throw new IllegalStateException(String.format("%s is not reachable after %s tries", serviceName, maxTries)); + } + } + + + protected String runCommand(String[] command) { + try { + LOG.info("Exec command: {}", StringUtils.join(command, " ")); + Process process = Runtime.getRuntime().exec(command); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + return reader.readLine(); + } catch (Exception e) { + throw new RuntimeException("Error during execute shell command: ", e); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchDockerSteps.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchDockerSteps.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchDockerSteps.java index 32e8cba..cb67fcc 100644 --- a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchDockerSteps.java +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchDockerSteps.java @@ -41,35 +41,13 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.URL; -public class LogSearchDockerSteps { +public class LogSearchDockerSteps extends AbstractLogSearchSteps { private static final Logger LOG = LoggerFactory.getLogger(LogSearchDockerSteps.class); @Given("logsearch docker container") public void setupLogSearchContainer() throws Exception { - boolean logsearchStarted = StoryDataRegistry.INSTANCE.isLogsearchContainerStarted(); - if (!logsearchStarted) { - LOG.info("Create new docker container for Log Search .."); - URL location = LogSearchDockerSteps.class.getProtectionDomain().getCodeSource().getLocation(); - String ambariFolder = new File(location.toURI()).getParentFile().getParentFile().getParentFile().getParent(); - StoryDataRegistry.INSTANCE.setAmbariFolder(ambariFolder); - String shellScriptLocation = ambariFolder + "/ambari-logsearch/docker/logsearch-docker.sh"; - StoryDataRegistry.INSTANCE.setShellScriptLocation(shellScriptLocation); - String output = runCommand(new String[]{StoryDataRegistry.INSTANCE.getShellScriptLocation(), "start"}); - LOG.info("Command output: {}", output); - StoryDataRegistry.INSTANCE.setLogsearchContainerStarted(true); - - // TODO: create a script which returns the proper host for docker, use: runCommand or an env variable - String dockerHostFromUri = "localhost"; - - StoryDataRegistry.INSTANCE.setDockerHost(dockerHostFromUri); - checkHostAndPortReachable(dockerHostFromUri, StoryDataRegistry.INSTANCE.getLogsearchPort(), "LogSearch"); - waitUntilSolrIsUp(); - waitUntilSolrHasAnyData(); - - LOG.info("Waiting for logfeeder to finish the test log parsings... (10 sec)"); - Thread.sleep(10000); - } + initDockerContainer(); } @When("logfeeder started (parse logs & send data to solr)") @@ -78,7 +56,7 @@ public class LogSearchDockerSteps { } @BeforeStories - public void checkDockerApi() { + public void initDocker() throws Exception { // TODO: check docker is up } @@ -86,92 +64,4 @@ public class LogSearchDockerSteps { public void removeLogSearchContainer() { runCommand(new String[]{StoryDataRegistry.INSTANCE.getShellScriptLocation(), "stop"}); } - - private void waitUntilSolrIsUp() throws Exception { - int maxTries = 30; - boolean solrIsUp = false; - for (int tries = 1; tries < maxTries; tries++) { - try { - SolrClient solrClient = new LBHttpSolrClient(String.format("http://%s:%d/solr/%s_shard0_replica1", - StoryDataRegistry.INSTANCE.getDockerHost(), - StoryDataRegistry.INSTANCE.getSolrPort(), - StoryDataRegistry.INSTANCE.getServiceLogsCollection())); - StoryDataRegistry.INSTANCE.setSolrClient(solrClient); - SolrPingResponse pingResponse = solrClient.ping(); - if (pingResponse.getStatus() != 0) { - LOG.info("Solr is not up yet, retrying... ({})", tries); - Thread.sleep(2000); - } else { - solrIsUp = true; - LOG.info("Solr is up and running"); - break; - } - } catch (Exception e) { - LOG.error("Error occurred during pinging solr ({}). retrying {} times", e.getMessage(), tries); - Thread.sleep(2000); - } - } - - if (!solrIsUp) { - throw new IllegalStateException(String.format("Solr is not up after %d tries", maxTries)); - } - } - - private void waitUntilSolrHasAnyData() throws IOException, SolrServerException, InterruptedException { - boolean solrHasData = false; - - int maxTries = 60; - for (int tries = 1; tries < maxTries; tries++) { - try { - SolrClient solrClient = StoryDataRegistry.INSTANCE.getSolrClient(); - SolrQuery solrQuery = new SolrQuery(); - solrQuery.setQuery("*:*"); - QueryResponse queryResponse = solrClient.query(solrQuery); - SolrDocumentList list = queryResponse.getResults(); - if (list.size() > 0) { - solrHasData = true; - break; - } else { - Thread.sleep(2000); - LOG.info("Solr has no data yet, retrying... ({} tries)", tries); - } - } catch (Exception e) { - LOG.error("Error occurred during checking solr ({}). retrying {} times", e.getMessage(), tries); - Thread.sleep(2000); - } - } - if (!solrHasData) { - throw new IllegalStateException(String.format("Solr has no data after %d tries", maxTries)); - } - } - - - private void checkHostAndPortReachable(String host, int port, String serviceName) throws InterruptedException { - boolean reachable = false; - int maxTries = 60; - for (int tries = 1; tries < maxTries; tries++ ) { - try (Socket socket = new Socket()) { - socket.connect(new InetSocketAddress(host, port), 1000); - reachable = true; - break; - } catch (IOException e) { - Thread.sleep(2000); - LOG.info("{} is not reachable yet, retrying..", serviceName); - } - } - if (!reachable) { - throw new IllegalStateException(String.format("%s is not reachable after %s tries", serviceName, maxTries)); - } - } - - - private String runCommand(String[] command) { - try { - Process process = Runtime.getRuntime().exec(command); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - return reader.readLine(); - } catch (Exception e) { - throw new RuntimeException("Error during execute shell command: ", e); - } - } } http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchUISteps.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchUISteps.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchUISteps.java new file mode 100644 index 0000000..b40a2bc --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/steps/LogSearchUISteps.java @@ -0,0 +1,212 @@ +/* + * 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.ambari.logsearch.steps; + +import junit.framework.Assert; +import org.apache.ambari.logsearch.domain.StoryDataRegistry; +import org.apache.ambari.logsearch.web.Home; +import org.jbehave.core.annotations.AfterScenario; +import org.jbehave.core.annotations.AfterStories; +import org.jbehave.core.annotations.AfterStory; +import org.jbehave.core.annotations.BeforeScenario; +import org.jbehave.core.annotations.BeforeStories; +import org.jbehave.core.annotations.BeforeStory; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Named; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; +import org.jbehave.web.selenium.WebDriverProvider; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +public class LogSearchUISteps extends AbstractLogSearchSteps { + + private static final Logger LOG = LoggerFactory.getLogger(LogSearchUISteps.class); + + private final WebDriverProvider driverProvider; + + private Home home; + + public LogSearchUISteps(WebDriverProvider driverProvider) { + this.driverProvider = driverProvider; + } + + @BeforeScenario + public void initHomePage() { + home = new Home(driverProvider); + LOG.info("Init home page: {}", home.getCurrentUrl()); + } + + @AfterScenario + public void deleteCookies() { + LOG.info("Delete all cookies..."); + home.manage().deleteAllCookies(); + } + + @BeforeStories + public void beforeStories() throws Exception { + initDockerContainer(); + LOG.info("Initialize web driver..."); + StoryDataRegistry.INSTANCE.getWebDriverProvider().initialize(); + LOG.info("Web driver details: {}", StoryDataRegistry.INSTANCE.getWebDriverProvider().get().toString()); + } + + @AfterStory + public void closePage() throws Exception { + LOG.info("Closing web driver"); + StoryDataRegistry.INSTANCE.getWebDriverProvider().end(); + } + + @Given("open logsearch home page") + public void initBrowser() { + LOG.info("Delete all cookies..."); + home.manage().deleteAllCookies(); + LOG.info("Open home page: {}", home.getCurrentUrl()); + home.open(); + } + + @When("login with $username / $password") + public void login(@Named("username") String userName, @Named("password") String password) { + LOG.info("Type username: {}", userName); + home.findElement(By.id("username")).sendKeys(userName); + LOG.info("Type password: {}", password); + home.findElement(By.id("password")).sendKeys(password); + LOG.info("Click on Sign In button."); + home.findElement(By.className("custLogin")).click(); + closeTourPopup(); + } + + @Then("page contains text: '$text'") + public void contains(@Named("text") String text) { + LOG.info("Check page contains text: '{}'", text); + home.found(text); + } + + @Then("page does not contain text: '$text'") + public void notContains(@Named("text") String text) { + LOG.info("Check page does not contain text: '{}'", text); + home.notFound(text); + } + + @When("wait $seconds seconds") + public void waitSeconds(@Named("second") String second) { + LOG.info("Wait {} seconds...", second); + home.manage().timeouts().implicitlyWait(Integer.parseInt(second), TimeUnit.SECONDS); + } + + @When("click on element: $xpath (xpath)") + public void clickOnElementByXPath(@Named("xpath") String xPath) { + LOG.info("Click on element by xpath: '{}'", xPath); + driverProvider.get().findElement(By.xpath(xPath)).click(); + } + + @When("click on element: $id (id)") + public void clickOnElementById(@Named("id") String id) { + LOG.info("Click on element by id: '{}'", id); + driverProvider.get().findElement(By.xpath(id)).click(); + } + + @When("click on element: $css (css selector)") + public void clickOnElementByCssSelector(@Named("css") String cssSelector) { + LOG.info("Click on element by css selector: '{}'", cssSelector); + driverProvider.get().findElement(By.cssSelector(cssSelector)).click(); + } + + @Then("element exists with xpath: $xpath") + public void findByXPath(@Named("xpath") String xPath) { + LOG.info("Find element by xpath: '{}'", xPath); + Assert.assertNotNull(home.findElement(By.xpath(xPath))); + } + + @Then("element exists with xpath: $id") + public void findById(@Named("id") String id) { + LOG.info("Find element by id: '{}'", id); + Assert.assertNotNull(home.findElement(By.id(id))); + } + + @Then("element exists with css selector: $css") + public void findByCssSelector(@Named("css") String cssSelector) { + LOG.info("Find element by css selector: '{}'", cssSelector); + Assert.assertNotNull(home.findElement(By.cssSelector(cssSelector))); + } + + @Then("element text equals '$text', with xpath $xpath") + public void equalsByXPath(@Named("text") String text, @Named("xpath") String xPath) { + LOG.info("Check text of the element (xpath: '{}') equals with '{}'", xPath, text); + Assert.assertEquals(text, home.findElement(By.xpath(xPath)).getText()); + } + + @Then("element text equals '$text' with id $id") + public void equalsyId(@Named("text") String text, @Named("id") String id) { + LOG.info("Check text of the element (id: '{}') equals with '{}'", id, text); + Assert.assertEquals(text, home.findElement(By.id(id)).getText()); + } + + @Then("element text equals '$text' with css selector $css") + public void equalsCssSelector(@Named("text") String text, @Named("css") String cssSelector) { + LOG.info("Check text of the element (css selector: '{}') equals with '{}'", cssSelector, text); + Assert.assertEquals(text, home.findElement(By.cssSelector(cssSelector)).getText()); + } + + @Then("element does not exist with xpath: $xpath") + public void doNotFindByXPath(@Named("xpath") String xPath) { + try { + LOG.info("Check that element does not exist with xpath: {}", xPath); + home.findElement(By.xpath(xPath)); + Assert.fail(String.format("Element is found. xPath: '%s'", xPath)); + } catch (NoSuchElementException e) { + // success + } + } + + @Then("element does not exist with xpath: $id") + public void doNotFindById(@Named("id") String id) { + try { + LOG.info("Check that element does not exist with id: {}", id); + home.findElement(By.xpath(id)); + Assert.fail(String.format("Element is found. id: '%s'", id)); + } catch (NoSuchElementException e) { + // success + } + } + + @Then("element does not exist with css selector: $css") + public void doNotFindByCssSelector(@Named("css") String cssSelector) { + try { + LOG.info("Check that element does not exist with css selector: {}", cssSelector); + home.findElement(By.xpath(cssSelector)); + Assert.fail(String.format("Element is found. css selector: '%s'", cssSelector)); + } catch (NoSuchElementException e) { + // success + } + } + + private void closeTourPopup() { + LOG.info("Close Tour popup if needed."); + try { + home.findElement(By.cssSelector("div.modal-footer > button.btn.btn-default")).click(); + } catch (NoSuchElementException ex) { + // do nothing - no popup + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchApiQueryStory.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchApiQueryStory.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchApiQueryStory.java deleted file mode 100644 index 45455bf..0000000 --- a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchApiQueryStory.java +++ /dev/null @@ -1,22 +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.ambari.logsearch.story; - -public class LogSearchApiQueryStory extends LogSearchStory { -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchBackendStories.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchBackendStories.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchBackendStories.java new file mode 100644 index 0000000..46f2928 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchBackendStories.java @@ -0,0 +1,84 @@ +/* + * 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.ambari.logsearch.story; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import org.apache.ambari.logsearch.steps.LogSearchApiSteps; +import org.apache.ambari.logsearch.steps.SolrSteps; +import org.apache.ambari.logsearch.steps.LogSearchDockerSteps; +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.configuration.MostUsefulConfiguration; +import org.jbehave.core.embedder.executors.SameThreadExecutors; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.io.StoryFinder; +import org.jbehave.core.io.StoryPathResolver; +import org.jbehave.core.io.UnderscoredCamelCaseResolver; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.junit.JUnitStory; +import org.jbehave.core.reporters.Format; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; +import org.junit.Test; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; + +public class LogSearchBackendStories extends JUnitStories { + + @Override + public Configuration configuration() { + return new MostUsefulConfiguration() + .useStoryLoader(new LoadFromClasspath(this.getClass())) + .useStoryReporterBuilder( + new StoryReporterBuilder().withFailureTrace(true).withDefaultFormats().withFormats(Format.CONSOLE, Format.TXT)); + } + + @Override + public InjectableStepsFactory stepsFactory() { + return new InstanceStepsFactory(configuration(), + new LogSearchDockerSteps(), + new SolrSteps(), + new LogSearchApiSteps()); + } + + @Test + public void run() throws Throwable { + super.run(); + } + + @Override + protected List<String> storyPaths() { + List<String> backendStories = new StoryFinder() + .findPaths(codeLocationFromClass(this.getClass()).getFile(), Arrays.asList("**/*.story"), null); + return Lists.newArrayList(Collections2.filter(backendStories, new Predicate<String>() { + @Override + public boolean apply(String storyFileName) { + return !storyFileName.endsWith("ui.story"); + } + })); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchStory.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchStory.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchStory.java deleted file mode 100644 index ce6b9cb..0000000 --- a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchStory.java +++ /dev/null @@ -1,60 +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.ambari.logsearch.story; - -import org.apache.ambari.logsearch.steps.LogSearchApiSteps; -import org.apache.ambari.logsearch.steps.SolrSteps; -import org.apache.ambari.logsearch.steps.LogSearchDockerSteps; -import org.jbehave.core.configuration.Configuration; -import org.jbehave.core.configuration.MostUsefulConfiguration; -import org.jbehave.core.io.LoadFromClasspath; -import org.jbehave.core.io.StoryPathResolver; -import org.jbehave.core.io.UnderscoredCamelCaseResolver; -import org.jbehave.core.junit.JUnitStory; -import org.jbehave.core.reporters.Format; -import org.jbehave.core.reporters.StoryReporterBuilder; -import org.jbehave.core.steps.InjectableStepsFactory; -import org.jbehave.core.steps.InstanceStepsFactory; -import org.junit.Test; - -abstract public class LogSearchStory extends JUnitStory { - @Override - public Configuration configuration() { - StoryPathResolver storyPathResolver = new UnderscoredCamelCaseResolver(".story"); - return new MostUsefulConfiguration() - .useStoryPathResolver(storyPathResolver) - .useStoryLoader(new LoadFromClasspath(this.getClass())) - .useStoryReporterBuilder( - new StoryReporterBuilder().withFailureTrace(true).withDefaultFormats().withFormats(Format.CONSOLE, Format.TXT)); - } - - @Override - public InjectableStepsFactory stepsFactory() { - return new InstanceStepsFactory(configuration(), - new LogSearchDockerSteps(), - new SolrSteps(), - new LogSearchApiSteps()); - } - - @Test - public void run() throws Throwable { - super.run(); - } - -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchUIStories.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchUIStories.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchUIStories.java new file mode 100644 index 0000000..eb2a180 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogSearchUIStories.java @@ -0,0 +1,93 @@ +/* + * 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.ambari.logsearch.story; + +import org.apache.ambari.logsearch.domain.StoryDataRegistry; +import org.apache.ambari.logsearch.steps.LogSearchDockerSteps; +import org.apache.ambari.logsearch.steps.LogSearchUISteps; +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.Embeddable; +import org.jbehave.core.embedder.executors.SameThreadExecutors; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.io.StoryFinder; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; +import org.jbehave.web.selenium.RemoteWebDriverProvider; +import org.jbehave.web.selenium.SeleniumConfiguration; +import org.jbehave.web.selenium.SeleniumContext; +import org.jbehave.web.selenium.WebDriverProvider; +import org.jbehave.web.selenium.WebDriverScreenshotOnFailure; +import org.openqa.selenium.Platform; +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; +import static org.jbehave.core.reporters.Format.CONSOLE; +import static org.jbehave.core.reporters.Format.HTML; +import static org.jbehave.core.reporters.Format.TXT; +import static org.jbehave.core.reporters.Format.XML; + +public class LogSearchUIStories extends JUnitStories { + + private WebDriverProvider driverProvider; + private SeleniumContext context; + + public LogSearchUIStories() { + // TODO: get docker host from a runCommand funtion + String hubUrl = "http://localhost:4444/wd/hub"; + System.setProperty("REMOTE_WEBDRIVER_URL", hubUrl); + DesiredCapabilities capability = DesiredCapabilities.firefox(); + capability.setPlatform(Platform.LINUX); + capability.setVersion("45.8.0"); + driverProvider = new RemoteWebDriverProvider(capability); + StoryDataRegistry.INSTANCE.setWebDriverProvider(driverProvider); + context = new SeleniumContext(); + configuredEmbedder().useExecutorService(new SameThreadExecutors().create(configuredEmbedder().embedderControls())); + } + + @Override + public Configuration configuration() { + Class<? extends Embeddable> embeddableClass = this.getClass(); + return new SeleniumConfiguration() + .useSeleniumContext(context) + .useWebDriverProvider(driverProvider) + .useStoryLoader(new LoadFromClasspath(embeddableClass)) + .useStoryReporterBuilder(new StoryReporterBuilder() + .withCodeLocation(codeLocationFromClass(embeddableClass)) + .withDefaultFormats() + .withFormats(CONSOLE, TXT, HTML, XML)); + } + + @Override + public InjectableStepsFactory stepsFactory() { + Configuration configuration = configuration(); + return new InstanceStepsFactory(configuration, new LogSearchDockerSteps(), new LogSearchUISteps(driverProvider), + new WebDriverScreenshotOnFailure(driverProvider, configuration.storyReporterBuilder())); + } + + @Override + protected List<String> storyPaths() { + return new StoryFinder() + .findPaths(codeLocationFromClass(this.getClass()).getFile(), Arrays.asList("**/*.ui.story"), null); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogfeederParsingStory.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogfeederParsingStory.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogfeederParsingStory.java deleted file mode 100644 index c502cc4..0000000 --- a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/story/LogfeederParsingStory.java +++ /dev/null @@ -1,22 +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.ambari.logsearch.story; - -public class LogfeederParsingStory extends LogSearchStory { -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/AbstractPage.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/AbstractPage.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/AbstractPage.java new file mode 100644 index 0000000..b6d0a58 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/AbstractPage.java @@ -0,0 +1,63 @@ +/* + * 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.ambari.logsearch.web; + +import org.jbehave.web.selenium.WebDriverPage; +import org.jbehave.web.selenium.WebDriverProvider; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.fail; + +public abstract class AbstractPage extends WebDriverPage { + + public AbstractPage(WebDriverProvider driverProvider) { + super(driverProvider); + } + + public void found(String text) { + found(getPageSource(), text); + } + + public void found(String pageSource, String text) { + if (!pageSource.contains(escapeHtml(text))) { + fail("Text: '" + text + "' not found in page '" + pageSource + "'"); + } + } + + public void found(List<String> texts) { + for (String text : texts) { + found(text); + } + } + + public void notFound(String text) { + notFound(getPageSource(), text); + } + + public void notFound(String pageSource, String text) { + assertThat(pageSource.contains(escapeHtml(text)), is(false)); + } + + private String escapeHtml(String text) { + return text.replace("<", "<").replace(">", ">"); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/Home.java ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/Home.java b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/Home.java new file mode 100644 index 0000000..6c576d4 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/java/org/apache/ambari/logsearch/web/Home.java @@ -0,0 +1,39 @@ +/* + * 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.ambari.logsearch.web; + +import org.apache.ambari.logsearch.domain.StoryDataRegistry; +import org.jbehave.web.selenium.WebDriverProvider; + +import java.util.concurrent.TimeUnit; + +public class Home extends AbstractPage { + + public Home(WebDriverProvider driverProvider) { + super(driverProvider); + } + + public void open() { + get(String.format("http://%s:%d/index.html", + StoryDataRegistry.INSTANCE.getDockerHost(), + StoryDataRegistry.INSTANCE.getLogsearchPort())); + manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/log_search_api_query_story.story ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/log_search_api_query_story.story b/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/log_search_api_query_story.story deleted file mode 100644 index cfaa359..0000000 --- a/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/log_search_api_query_story.story +++ /dev/null @@ -1,17 +0,0 @@ -Meta: - -Narrative: -As a user -I want to perform queries against Log Search api -So that I can validate the json outputs - -Scenario: scenario description - -Given logsearch docker container -When LogSearch api query sent: <apiQuery> -Then The api query result is <jsonResult> - -Examples: -|apiQuery|jsonResult| -|/api/v1/service/logs/schema/fields|service-log-schema.json| -|/api/v1/service/logs/levels/counts?page=0&pageSize=25&startIndex=0&q=*%3A*|service-log-level-counts-values.json| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/logfeeder_parsing_story.story ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/logfeeder_parsing_story.story b/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/logfeeder_parsing_story.story deleted file mode 100644 index 388e624..0000000 --- a/ambari-logsearch/ambari-logsearch-it/src/test/resources/org/apache/ambari/logsearch/story/logfeeder_parsing_story.story +++ /dev/null @@ -1,20 +0,0 @@ -Story Service logs are parsed and stored into Solr - -Narrative: -As a user -I want to start logsearch/logfeeder/solr components in a docker container with test logs -So that I can parse and store the logs into Solr - -Scenario: Number of logs for components - -Given logsearch docker container -When logfeeder started (parse logs & send data to solr) -Then the number of <component> docs is: <docSize> - -Examples: -|component|docSize| -|logsearch_app|1| -|zookeeper|3| -|hst_agent|4| -|secure_log|11| -|system_message|17| http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/log_search_api_query_story.story ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/log_search_api_query_story.story b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/log_search_api_query_story.story new file mode 100644 index 0000000..0af00f5 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/log_search_api_query_story.story @@ -0,0 +1,17 @@ +Meta: + +Narrative: +As a user +I want to perform queries against Log Search api +So that I can validate the json outputs + +Scenario: Log Search API JSON responses + +Given logsearch docker container +When LogSearch api query sent: <apiQuery> +Then The api query result is <jsonResult> + +Examples: +|apiQuery|jsonResult| +|/api/v1/service/logs/schema/fields|service-log-schema.json| +|/api/v1/service/logs/levels/counts?page=0&pageSize=25&startIndex=0&q=*%3A*|service-log-level-counts-values.json| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/logfeeder_parsing_story.story ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/logfeeder_parsing_story.story b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/logfeeder_parsing_story.story new file mode 100644 index 0000000..388e624 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/backend/logfeeder_parsing_story.story @@ -0,0 +1,20 @@ +Story Service logs are parsed and stored into Solr + +Narrative: +As a user +I want to start logsearch/logfeeder/solr components in a docker container with test logs +So that I can parse and store the logs into Solr + +Scenario: Number of logs for components + +Given logsearch docker container +When logfeeder started (parse logs & send data to solr) +Then the number of <component> docs is: <docSize> + +Examples: +|component|docSize| +|logsearch_app|1| +|zookeeper|3| +|hst_agent|4| +|secure_log|11| +|system_message|17| http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/selenium/login.ui.story ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/selenium/login.ui.story b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/selenium/login.ui.story new file mode 100644 index 0000000..543c211 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-it/src/test/resources/stories/selenium/login.ui.story @@ -0,0 +1,20 @@ +Meta: + +Narrative: +As a user +I want to start LogSearch services and login to the UI +So that I can validate the proper user + +Scenario: login with admin/admin + +Given logsearch docker container +And open logsearch home page +When login with admin / admin +Then page contains text: 'Service Logs' + +Scenario: login with admin and wrong password + +Given logsearch docker container +And open logsearch home page +When login with admin / wrongpassword +Then page does not contain text: 'Service Logs' \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/docker/Dockerfile ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/Dockerfile b/ambari-logsearch/docker/Dockerfile index 6e8ea3e..d399fc6 100644 --- a/ambari-logsearch/docker/Dockerfile +++ b/ambari-logsearch/docker/Dockerfile @@ -15,17 +15,22 @@ FROM centos:centos6 RUN echo root:changeme | chpasswd RUN yum clean all -y && yum update -y -RUN yum -y install vim wget rpm-build sudo which telnet tar openssh-server openssh-clients ntp git python-setuptools python-devel httpd lsof +RUN yum -y install firefox-45.8.0-2.el6.centos xvfb xeyes vim wget rpm-build sudo which telnet tar openssh-server openssh-clients ntp git python-setuptools python-devel httpd lsof RUN rpm -e --nodeps --justdb glibc-common RUN yum -y install glibc-common ENV HOME /root #Install JAVA -RUN wget --no-check-certificate --no-cookies --header "Cookie:oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u55-b13/jdk-7u55-linux-x64.rpm -O jdk-7u55-linux-x64.rpm -RUN rpm -ivh jdk-7u55-linux-x64.rpm +ENV JAVA_VERSION 8u31 +ENV BUILD_VERSION b13 +RUN wget --no-cookies --no-check-certificate --header "Cookie: oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/$JAVA_VERSION-$BUILD_VERSION/jdk-$JAVA_VERSION-linux-x64.rpm" -O jdk-8-linux-x64.rpm +RUN rpm -ivh jdk-8-linux-x64.rpm ENV JAVA_HOME /usr/java/default/ +#Install Selenium server +RUN wget --no-check-certificate -O /root/selenium-server-standalone.jar http://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.1.jar + #Install Maven RUN mkdir -p /opt/maven WORKDIR /opt/maven @@ -34,7 +39,7 @@ RUN tar -xvzf /opt/maven/apache-maven-3.0.5-bin.tar.gz RUN rm -rf /opt/maven/apache-maven-3.0.5-bin.tar.gz ENV M2_HOME /opt/maven/apache-maven-3.0.5 -ENV MAVEN_OPTS -Xmx2048m -XX:MaxPermSize=256m +ENV MAVEN_OPTS -Xmx2048m ENV PATH $PATH:$JAVA_HOME/bin:$M2_HOME/bin # SSH key @@ -42,6 +47,8 @@ RUN ssh-keygen -f /root/.ssh/id_rsa -t rsa -N '' RUN cat /root/.ssh/id_rsa.pub > /root/.ssh/authorized_keys RUN chmod 600 /root/.ssh/authorized_keys RUN sed -ri 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config +RUN echo 'X11Forwarding yes\n' /etc/ssh/sshd_config +RUN echo 'X11DisplayOffset 10\n' /etc/ssh/sshd_config #To allow bower install behind proxy. See https://github.com/bower/bower/issues/731 RUN git config --global url."https://".insteadOf git:// @@ -54,7 +61,7 @@ RUN npm install -g brunch@1.7.20 # Install Solr ENV SOLR_VERSION 5.5.2 -RUN wget --no-check-certificate -O /root/solr-$SOLR_VERSION.tgz http://archive.apache.org/dist/lucene/solr/$SOLR_VERSION/solr-$SOLR_VERSION.tgz +RUN wget --no-check-certificate -O /root/solr-$SOLR_VERSION.tgz http://public-repo-1.hortonworks.com/ARTIFACTS/dist/lucene/solr/$SOLR_VERSION/solr-$SOLR_VERSION.tgz RUN cd /root && tar -zxvf /root/solr-$SOLR_VERSION.tgz ADD bin/start.sh /root/start.sh ADD test-config /root/test-config http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/docker/bin/start.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/bin/start.sh b/ambari-logsearch/docker/bin/start.sh index 1efc85c..28ebf65 100644 --- a/ambari-logsearch/docker/bin/start.sh +++ b/ambari-logsearch/docker/bin/start.sh @@ -92,6 +92,10 @@ function start_logfeeder() { touch /var/log/ambari-logsearch-logfeeder/logsearch-logfeeder.log } +function start_selenium_server() { + nohup java -jar /root/selenium-server-standalone.jar > /var/log/selenium-test.log & +} + function log() { component_log=${COMPONENT_LOG:-"logsearch"} case $component_log in @@ -101,6 +105,9 @@ function log() { "solr") tail -f /var/log/ambari-logsearch-solr/solr.log ;; + "selenium") + tail -f /var/log/selenium-test.log + ;; *) tail -f /var/log/ambari-logsearch-portal/logsearch-app.log ;; @@ -109,6 +116,7 @@ function log() { create_config generate_keys +start_selenium_server start_solr start_logsearch start_logfeeder http://git-wip-us.apache.org/repos/asf/ambari/blob/3153b9bc/ambari-logsearch/docker/logsearch-docker.sh ---------------------------------------------------------------------- diff --git a/ambari-logsearch/docker/logsearch-docker.sh b/ambari-logsearch/docker/logsearch-docker.sh index eab850e..4d53fa1 100755 --- a/ambari-logsearch/docker/logsearch-docker.sh +++ b/ambari-logsearch/docker/logsearch-docker.sh @@ -30,6 +30,11 @@ function build_logsearch_container() { popd } +function get_docker_ip() { + local ip=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}') + echo $ip +} + function start_logsearch_container() { setup_profile source $sdir/Profile @@ -38,9 +43,10 @@ function start_logsearch_container() { popd : ${MAVEN_REPOSITORY_LOCATION:?"Please set the MAVEN_REPOSITORY_LOCATION in Profile"} kill_logsearch_container + local docker_ip=$(get_docker_ip) echo "Run Log Search container" - docker run -d --name logsearch --hostname logsearch.apache.org \ - -v $AMBARI_LOCATION:/root/ambari -v $MAVEN_REPOSITORY_LOCATION:/root/.m2 $LOGSEARCH_EXPOSED_PORTS $LOGSEARCH_ENV_OPTS $LOGSEARCH_EXTRA_OPTS $LOGSEARCH_VOLUME_OPTS -p 9983:9983 \ + docker run -d --name logsearch --hostname logsearch.apache.org -e DISPLAY=$docker_ip:0 \ + -v $AMBARI_LOCATION:/root/ambari -v $MAVEN_REPOSITORY_LOCATION:/root/.m2 $LOGSEARCH_EXPOSED_PORTS $LOGSEARCH_ENV_OPTS $LOGSEARCH_EXTRA_OPTS $LOGSEARCH_VOLUME_OPTS -p 9983:9983 -p 4444:4444 -p 5910:5910 \ -v $AMBARI_LOCATION/ambari-logsearch/ambari-logsearch-logfeeder/target/classes:/root/ambari/ambari-logsearch/ambari-logsearch-logfeeder/target/package/classes \ -v $AMBARI_LOCATION/ambari-logsearch/ambari-logsearch-server/target/classes:/root/ambari/ambari-logsearch/ambari-logsearch-server/target/package/classes \ -v $AMBARI_LOCATION/ambari-logsearch/ambari-logsearch-web/src/main/webapp:/root/ambari/ambari-logsearch/ambari-logsearch-server/target/package/classes/webapps/app \