http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.java deleted file mode 100644 index 60eeabd..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/BaseRequest.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.falcon.request; - -import org.apache.commons.net.util.TrustManagerUtils; -import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; -import org.apache.falcon.regression.core.util.Config; -import org.apache.falcon.security.FalconAuthorizationToken; -import org.apache.hadoop.security.authentication.client.AuthenticatedURL; -import org.apache.hadoop.security.authentication.client.AuthenticationException; -import org.apache.hadoop.security.authentication.client.PseudoAuthenticator; -import org.apache.http.Header; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.conn.ssl.AllowAllHostnameVerifier; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.BasicClientConnectionManager; -import org.apache.http.message.BasicHeader; -import org.apache.http.util.EntityUtils; -import org.apache.log4j.Logger; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.List; - -/** Class for making rest requests. */ -public class BaseRequest { - - private static final boolean AUTHENTICATE = setAuthenticate(); - private static final Logger LOGGER = Logger.getLogger(BaseRequest.class); - - private String method; - private String url; - private List<Header> headers; - private String requestData; - private String user; - private URI uri; - private HttpHost target; - private static final SSLSocketFactory SSL_SOCKET_FACTORY; - - static { - try { - SSLContext ssl = getSslContext(); - SSL_SOCKET_FACTORY = new SSLSocketFactory(ssl, new AllowAllHostnameVerifier()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static SSLContext getSslContext() throws Exception { - SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init( - null, - new TrustManager[]{TrustManagerUtils.getValidateServerCertificateTrustManager()}, - new SecureRandom()); - return sslContext; - } - - public BaseRequest(String url, String method, String user) throws URISyntaxException { - this(url, method, user, null); - } - - public BaseRequest(String url, String method, String user, String data) - throws URISyntaxException { - this.method = method; - this.url = url; - this.requestData = null; - this.user = (null == user) ? MerlinConstants.CURRENT_USER_NAME : user; - this.uri = new URI(url); - target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()); - this.headers = new ArrayList<>(); - this.requestData = data; - } - - private static boolean setAuthenticate() { - String value = Config.getProperty("isAuthenticationSet"); - value = (null == value) ? "true" : value; - return !value.equalsIgnoreCase("false"); - } - - public void addHeader(String name, String value) { - headers.add(new BasicHeader(name, value)); - } - - public HttpResponse run() throws URISyntaxException, IOException, AuthenticationException, - InterruptedException { - URIBuilder uriBuilder = new URIBuilder(this.url); - - /*falcon now reads a user.name parameter in the request. - by default we will add it to every request.*/ - uriBuilder.addParameter(PseudoAuthenticator.USER_NAME, this.user); - uri = uriBuilder.build(); - this.url=uri.toString(); - // process the get - if (this.method.equalsIgnoreCase("get")) { - return execute(new HttpGet(this.url)); - } else if (this.method.equalsIgnoreCase("delete")) { - return execute(new HttpDelete(this.url)); - } - - HttpEntityEnclosingRequest request = null; - if (this.method.equalsIgnoreCase("post")) { - request = new HttpPost(new URI(this.url)); - } else if (this.method.equalsIgnoreCase("put")) { - request = new HttpPut(new URI(this.url)); - } else { - throw new IOException("Unknown method: " + method); - } - if (this.requestData != null) { - request.setEntity(new StringEntity(requestData)); - } - return execute(request); - } - - private HttpResponse execute(HttpRequest request) - throws IOException, AuthenticationException, InterruptedException { - // add headers to the request - if (null != headers && headers.size() > 0) { - for (Header header : headers) { - request.addHeader(header); - } - } - /*get the token and add it to the header. - works in secure and un secure mode.*/ - AuthenticatedURL.Token token; - if (AUTHENTICATE) { - token = FalconAuthorizationToken.getToken(user, uri.getScheme(), - uri.getHost(), uri.getPort()); - request.addHeader(RequestKeys.COOKIE, RequestKeys.AUTH_COOKIE_EQ + token); - } - - HttpClient client; - if (uri.toString().startsWith("https")) { - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("https", uri.getPort(), SSL_SOCKET_FACTORY)); - BasicClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry); - client = new DefaultHttpClient(cm); - } else { - client = new DefaultHttpClient(); - } - LOGGER.info("Request Url: " + request.getRequestLine().getUri()); - LOGGER.info("Request Method: " + request.getRequestLine().getMethod()); - - for (Header header : request.getAllHeaders()) { - LOGGER.info(String.format("Request Header: Name=%s Value=%s", header.getName(), - header.getValue())); - } - HttpResponse response = client.execute(target, request); - - /*incase the cookie is expired and we get a negotiate error back, generate the token again - and send the request*/ - if ((response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED)) { - Header[] wwwAuthHeaders = response.getHeaders(RequestKeys.WWW_AUTHENTICATE); - if (wwwAuthHeaders != null && wwwAuthHeaders.length != 0 - && wwwAuthHeaders[0].getValue().trim().startsWith(RequestKeys.NEGOTIATE)) { - if (AUTHENTICATE) { - token = FalconAuthorizationToken.getToken(user, uri.getScheme(), - uri.getHost(), uri.getPort(), true); - request.removeHeaders(RequestKeys.COOKIE); - request.addHeader(RequestKeys.COOKIE, RequestKeys.AUTH_COOKIE_EQ + token); - } - LOGGER.info("Request Url: " + request.getRequestLine().getUri()); - LOGGER.info("Request Method: " + request.getRequestLine().getMethod()); - for (Header header : request.getAllHeaders()) { - LOGGER.info(String.format("Request Header: Name=%s Value=%s", header.getName(), - header.getValue())); - } - // Must call this to release the connection - EntityUtils.consume(response.getEntity()); - response = client.execute(target, request); - } - } - LOGGER.info("Response Status: " + response.getStatusLine()); - for (Header header : response.getAllHeaders()) { - LOGGER.info(String.format("Response Header: Name=%s Value=%s", header.getName(), - header.getValue())); - } - return response; - } -}
http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java deleted file mode 100644 index 05d5fc6..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/request/RequestKeys.java +++ /dev/null @@ -1,36 +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.falcon.request; - -/** Class containing different request keys. */ -public final class RequestKeys { - private RequestKeys() { - throw new AssertionError("Instantiating utility class..."); - } - - public static final String CONTENT_TYPE_HEADER = "Content-Type"; - public static final String XML_CONTENT_TYPE = "text/xml"; - public static final String JSON_CONTENT_TYPE = "application/json"; - - public static final String AUTH_COOKIE = "hadoop.auth"; - public static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "="; - public static final String COOKIE = "Cookie"; - public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - public static final String NEGOTIATE = "Negotiate"; -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin-core/src/main/java/org/apache/falcon/security/FalconAuthorizationToken.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/security/FalconAuthorizationToken.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/security/FalconAuthorizationToken.java deleted file mode 100644 index 7ab8f9a..0000000 --- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/security/FalconAuthorizationToken.java +++ /dev/null @@ -1,115 +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.falcon.security; - -import org.apache.falcon.regression.core.util.KerberosHelper; -import org.apache.falcon.request.BaseRequest; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.authentication.client.AuthenticatedURL; -import org.apache.hadoop.security.authentication.client.AuthenticationException; -import org.apache.hadoop.security.authentication.client.KerberosAuthenticator; -import org.apache.hadoop.security.authentication.client.PseudoAuthenticator; -import org.apache.log4j.Logger; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; -import java.io.IOException; -import java.net.URL; -import java.security.PrivilegedExceptionAction; -import java.util.concurrent.ConcurrentHashMap; - -/** Class for obtaining authorization token. */ -public final class FalconAuthorizationToken { - private static final String AUTH_URL = "api/options"; - private static final KerberosAuthenticator AUTHENTICATOR = new KerberosAuthenticator(); - private static final FalconAuthorizationToken INSTANCE = new FalconAuthorizationToken(); - private static final Logger LOGGER = Logger.getLogger(FalconAuthorizationToken.class); - - // Use a hashmap so that we can cache the tokens. - private final ConcurrentHashMap<String, AuthenticatedURL.Token> tokens = - new ConcurrentHashMap<>(); - - private FalconAuthorizationToken() { - } - - public static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession sslSession) { - return true; - } - }; - - private static void authenticate(String user, String protocol, String host, int port) - throws IOException, AuthenticationException, InterruptedException { - final URL url = new URL(String.format("%s://%s:%d/%s", protocol, host, port, - AUTH_URL + "?" + PseudoAuthenticator.USER_NAME + "=" + user)); - LOGGER.info("Authorize using url: " + url.toString()); - - final AuthenticatedURL.Token currentToken = new AuthenticatedURL.Token(); - - /*using KerberosAuthenticator which falls back to PsuedoAuthenticator - instead of passing authentication type from the command line - bad factory*/ - try { - HttpsURLConnection.setDefaultSSLSocketFactory(BaseRequest.getSslContext() - .getSocketFactory()); - } catch (Exception e) { - throw new RuntimeException(e); - } - HttpsURLConnection.setDefaultHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER); - UserGroupInformation callerUGI = KerberosHelper.getUGI(user); - callerUGI.doAs(new PrivilegedExceptionAction<Void>() { - @Override - public Void run() throws Exception { - new AuthenticatedURL(AUTHENTICATOR).openConnection(url, currentToken); - return null; - } - }); - String key = getKey(user, protocol, host, port); - - // initialize a hash map if its null. - LOGGER.info("Authorization Token: " + currentToken.toString()); - INSTANCE.tokens.put(key, currentToken); - } - - public static AuthenticatedURL.Token getToken(String user, String protocol, String host, - int port, boolean overWrite) - throws IOException, AuthenticationException, InterruptedException { - String key = getKey(user, protocol, host, port); - - /*if the tokens are null or if token is not found then we will go ahead and authenticate - or if we are asked to overwrite*/ - if (!INSTANCE.tokens.containsKey(key) || overWrite) { - authenticate(user, protocol, host, port); - } - return INSTANCE.tokens.get(key); - } - - public static AuthenticatedURL.Token getToken(String user, String protocol, String host, - int port) - throws IOException, AuthenticationException, InterruptedException { - return getToken(user, protocol, host, port, false); - } - - /*spnego token will be unique to the user and uri its being requested for. - Hence the key of the hash map is the combination of user, protocol, host and port.*/ - private static String getKey(String user, String protocol, String host, int port) { - return String.format("%s-%s-%s-%d", user, protocol, host, port); - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/pom.xml ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/pom.xml b/falcon-regression/merlin/pom.xml deleted file mode 100644 index e624925..0000000 --- a/falcon-regression/merlin/pom.xml +++ /dev/null @@ -1,94 +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. - --> - -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.apache.falcon.regression</groupId> - <artifactId>falcon-regression</artifactId> - <version>0.10-SNAPSHOT</version> - </parent> - <artifactId>falcon-merlin</artifactId> - <description>Merlin - Regression test suite for Apache Falcon</description> - <name>Apache Falcon Regression Suite</name> - <packaging>jar</packaging> - <profiles> - <profile> - <id>hadoop-2</id> - <dependencies> - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-common</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-client</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hive.hcatalog</groupId> - <artifactId>hive-webhcat-java-client</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-hdfs</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-azure</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-distcp</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.hive</groupId> - <artifactId>hive-jdbc</artifactId> - </dependency> - <dependency> - <groupId>org.apache.hive</groupId> - <artifactId>hive-metastore</artifactId> - </dependency> - - - </dependencies> - </profile> - </profiles> - <dependencies> - <dependency> - <groupId>org.apache.falcon.regression</groupId> - <artifactId>falcon-merlin-core</artifactId> - </dependency> - <dependency> - <groupId>org.testng</groupId> - <artifactId>testng</artifactId> - </dependency> - <!-- Added so that at run time log4j is avaialble to capture the logs --> - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - </dependency> - </dependencies> -</project> http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseTestClass.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseTestClass.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseTestClass.java deleted file mode 100644 index f32da2d..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseTestClass.java +++ /dev/null @@ -1,145 +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.falcon.regression.testHelper; - -import org.apache.falcon.regression.core.bundle.Bundle; -import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.falcon.regression.core.util.CleanupUtil; -import org.apache.falcon.regression.core.util.Config; -import org.apache.falcon.regression.core.util.HadoopUtil; -import org.apache.hadoop.fs.FileSystem; -import org.apache.log4j.Logger; -import org.apache.oozie.client.OozieClient; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Base class for test classes. - */ -public class BaseTestClass { - private static String[] serverNames; - private static final Logger LOGGER = Logger.getLogger(BaseTestClass.class); - - static { - prepareProperties(); - } - - protected ColoHelper prism; - protected List<ColoHelper> servers; - protected List<FileSystem> serverFS; - protected List<OozieClient> serverOC; - private String baseHDFSDir = "/tmp/falcon-regression"; - public static final String PRISM_PREFIX = "prism"; - protected Bundle[] bundles; - public static final String MINUTE_DATE_PATTERN = "/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}"; - - - public BaseTestClass() { - // loginFromKeytab as the current user - prism = new ColoHelper(PRISM_PREFIX); - servers = getServers(); - serverFS = new ArrayList<>(); - serverOC = new ArrayList<>(); - try { - for (ColoHelper server : servers) { - serverFS.add(server.getClusterHelper().getHadoopFS()); - serverOC.add(server.getClusterHelper().getOozieClient()); - } - cleanTestsDirs(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - bundles = new Bundle[serverNames.length]; - removeTestClassEntities(); - } - - protected final String cleanAndGetTestDir() { - String dir = baseHDFSDir + '/' + this.getClass().getSimpleName(); - try { - HadoopUtil.recreateDir(serverFS, dir); - } catch (IOException e) { - throw new RuntimeException(e); - } - return dir; - } - - private static void prepareProperties() { - - serverNames = Config.getStringArray("servers"); - for (int i = 0; i < serverNames.length; i++) { - serverNames[i] = serverNames[i].trim(); - } - } - - private List<ColoHelper> getServers() { - ArrayList<ColoHelper> returnList = new ArrayList<>(); - for (String serverName : serverNames) { - returnList.add(new ColoHelper(serverName)); - } - return returnList; - } - - public void uploadDirToClusters(final String dstHdfsDir, final String localLocation) - throws IOException { - LOGGER.info(String.format("Uploading local dir: %s to all the clusters at: %s", - localLocation, dstHdfsDir)); - for (FileSystem fs : serverFS) { - HadoopUtil.uploadDir(fs, dstHdfsDir, localLocation); - } - } - - /** - * Method removes test class entities which belong to default test user. - */ - public final void removeTestClassEntities() { - removeTestClassEntities(new String[]{null}); - } - - /** - * This method removes all entities which name starts with prefix derived from test class name. As entities can - * belong to different users, that users need to be listed as parameters. Note that null is a default test user. - * @param users users whose entities should be removed. - */ - public final void removeTestClassEntities(String...users) { - for (String user : users) { - for (Bundle bundle : this.bundles) { - if (bundle != null) { - bundle.deleteBundle(prism); - } - } - String className = this.getClass().getSimpleName(); - CleanupUtil.cleanEntitiesWithPrefix(prism, className, user); - String deprecatedPrefix = 'A' + Integer.toHexString(className.hashCode()); - CleanupUtil.cleanEntitiesWithPrefix(prism, deprecatedPrefix, user); - } - } - - - public final void cleanTestsDirs() throws IOException { - if (MerlinConstants.CLEAN_TESTS_DIR) { - for (FileSystem fs : serverFS) { - HadoopUtil.deleteDirIfExists(baseHDFSDir, fs); - } - } - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseUITestClass.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseUITestClass.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseUITestClass.java deleted file mode 100644 index 09b8265..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/testHelper/BaseUITestClass.java +++ /dev/null @@ -1,70 +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.falcon.regression.testHelper; - -import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; -import org.apache.falcon.regression.core.util.Config; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.Point; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.firefox.FirefoxProfile; - -import java.util.concurrent.TimeUnit; - -/** - * Base class for UI test classes. - */ -public class BaseUITestClass extends BaseTestClass{ - - private static WebDriver driver; - - public static WebDriver getDriver() { - return driver; - } - - protected static void openBrowser() { - - FirefoxProfile profile = new FirefoxProfile(); - profile.setPreference("network.negotiate-auth.trusted-uris", MerlinConstants.PRISM_URL); - - driver = new FirefoxDriver(profile); - driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); - - int width = Config.getInt("browser.window.width", 0); - int height = Config.getInt("browser.window.height", 0); - - if (width * height == 0) { - driver.manage().window().maximize(); - } else { - driver.manage().window().setPosition(new Point(0, 0)); - driver.manage().window().setSize(new Dimension(width, height)); - } - - } - - - public static void closeBrowser() { - if (driver != null) { - driver.close(); - driver.quit(); - driver = null; - } - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntitiesPage.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntitiesPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntitiesPage.java deleted file mode 100644 index b175470..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntitiesPage.java +++ /dev/null @@ -1,122 +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.falcon.regression.ui.pages; - - -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.log4j.Logger; -import org.openqa.selenium.By; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Page with list of entities. - */ -public class EntitiesPage extends Page { - - protected static final String ENTITIES_TABLE = "//table[@id='entity-list']/tbody/tr"; - - private static final Logger LOGGER = Logger.getLogger(EntitiesPage.class); - private static final String ACTIVE_NXT_BTN = "//ul/li[not(@class)]/a[contains(text(),'»')]"; - private static final String PAGE_NUMBER = "//ul[@class='pagination']/li[@class='active']/a"; - - public EntitiesPage(WebDriver driver, ColoHelper helper, EntityType type) { - super(driver, helper); - url += "/index.html?type=" + type.toString().toLowerCase(); - - expectedElement = ENTITIES_TABLE; - notFoundMsg = String.format("No entities on %sS page", type); - } - - /** - * Returns status of defined entity. - * @param entityName name of entity - * @return status of defined entity - */ - public EntityStatus getEntityStatus(String entityName) { - navigateTo(); - while (true) { - String status = getEntitiesOnPage().get(entityName); - if (status != null) { - return EntityStatus.valueOf(status); - } - if (nextPagePresent()) { - goNextPage(); - } else { - break; - } - } - return null; - } - - /** - * Loads next page. - */ - private void goNextPage() { - LOGGER.info("Navigating to next page..."); - WebElement nextButton = driver.findElement(By.xpath(ACTIVE_NXT_BTN)); - nextButton.click(); - waitForElement(expectedElement, DEFAULT_TIMEOUT, "Next page didn't load"); - } - - - /** - * Checks if next page is present. - * @return true if next page is present - */ - - private boolean nextPagePresent() { - LOGGER.info("Checking if next page is present..."); - try { - new WebDriverWait(driver, DEFAULT_TIMEOUT).until(new Condition(ACTIVE_NXT_BTN, true)); - return true; - } catch (TimeoutException e) { - return false; - } - } - - /** - * Returns page number. - * @return page number - */ - public int getPageNumber() { - String number = driver.findElement(By.xpath(PAGE_NUMBER)).getText(); - return Integer.parseInt(number); - } - - private Map<String, String> getEntitiesOnPage() { - LOGGER.info("Reading all entities on page..."); - List<WebElement> lines = driver.findElements(By.xpath(ENTITIES_TABLE)); - Map<String, String> entities = new HashMap<>(); - for (WebElement line : lines) { - WebElement name = line.findElement(By.xpath("./td[1]/a")); - WebElement status = line.findElement(By.xpath("./td[2]")); - entities.put(name.getText(), status.getText()); - } - return entities; - } - -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntityPage.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntityPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntityPage.java deleted file mode 100644 index 6b6d17f..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/EntityPage.java +++ /dev/null @@ -1,81 +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.falcon.regression.ui.pages; - - -import org.apache.falcon.entity.v0.cluster.Cluster; -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.entity.v0.feed.Feed; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import java.io.StringReader; - -/** - * Page of entity (feed or process or cluster). - * @param <T> type of entity - */ -public class EntityPage<T> extends Page { - - private Class<T> type; - - protected EntityPage(WebDriver driver, ColoHelper helper, EntityType type, Class<T> entity, String entityName) { - super(driver, helper); - url += String.format("/entity.html?type=%s&id=%s", type.toString().toLowerCase(), entityName); - this.type = entity; - expectedElement = "//textarea[@id='entity-def-textarea' and contains(text(), 'xml')]"; - notFoundMsg = String.format(" %s '%s' not found!", type, entityName); - } - - /** - * Returns page of defined CLUSTER entity. - * @param entityName name of defined entity - * @return page of defined CLUSTER entity - */ - public static EntityPage<Cluster> getClusterPage(WebDriver driver, ColoHelper helper, String entityName) { - return new EntityPage<>(driver, helper, EntityType.CLUSTER, Cluster.class, entityName); - } - - /** - * Returns page of defined FEED entity. - * @param entityName name of defined entity - * @return page of defined FEED entity - */ - public static EntityPage<Feed> getFeedPage(WebDriver driver, ColoHelper helper, String entityName) { - return new EntityPage<>(driver, helper, EntityType.FEED, Feed.class, entityName); - } - - /** - * Returns entity object. - * @return entity object - * @throws JAXBException - */ - @SuppressWarnings("unchecked") - public T getEntity() throws JAXBException { - String entity = driver.findElement(By.id("entity-def-textarea")).getText(); - JAXBContext jc = JAXBContext.newInstance(type); - Unmarshaller u = jc.createUnmarshaller(); - return (T) u.unmarshal(new StringReader(entity)); - } - -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/Page.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/Page.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/Page.java deleted file mode 100644 index f176949..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/Page.java +++ /dev/null @@ -1,163 +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.falcon.regression.ui.pages; - -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.falcon.regression.core.util.TimeUtil; -import org.apache.log4j.Logger; -import org.openqa.selenium.By; -import org.openqa.selenium.SearchContext; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.ExpectedCondition; -import org.openqa.selenium.support.ui.WebDriverWait; - - -/** - * Abstract page of Falcon UI. - */ -public abstract class Page { - protected static final int DEFAULT_TIMEOUT = 10; - protected String url; - protected WebDriver driver; - - protected String expectedElement; - protected String notFoundMsg; - - private static final Logger LOGGER = Logger.getLogger(Page.class); - - Page(WebDriver driver, ColoHelper helper) { - this.driver = driver; - url = helper.getClusterHelper().getHostname(); - } - - public Page(WebDriver driver) { - this.driver = driver; - } - /** - * Go to page in browser. - */ - public void navigateTo() { - LOGGER.info("Navigating to " + url); - driver.get(url); - waitForElement(expectedElement, DEFAULT_TIMEOUT, notFoundMsg); - } - - /** - * Refresh page. - */ - public void refresh() { - LOGGER.info("Refreshing page " + url); - driver.navigate().refresh(); - } - - /** - * Wait for some WebElement defined by xpath. Throws TimeoutException if element is not visible after defined time. - * @param webElement find xpath inside this WebElement - * @param xpath xpath of expected WebElement - * @param timeoutSeconds how many seconds we should wait for element - * @param errMessage message for TimeoutException - */ - public void waitForElement(WebElement webElement, final String xpath, - final long timeoutSeconds, String errMessage) { - waitForElementAction(webElement, xpath, timeoutSeconds, errMessage, true); - } - - /** - * Wait for some WebElement defined by xpath. Throws TimeoutException if element is not visible after defined time. - * @param xpath xpath of expected WebElement - * @param timeoutSeconds how many seconds we should wait for element - * @param errMessage message for TimeoutException - */ - public void waitForElement(final String xpath, final long timeoutSeconds, String errMessage) { - waitForElementAction(null, xpath, timeoutSeconds, errMessage, true); - } - - /** - * Wait until WebElement disappears. - * @param xpath xpath of expected WebElement - * @param timeoutSeconds how many seconds we should wait for disappearing - * @param errMessage message for TimeoutException - */ - public void waitForDisappear(final String xpath, final long timeoutSeconds, String errMessage) { - waitForElementAction(null, xpath, timeoutSeconds, errMessage, false); - } - - /** - * Wait until WebElement became visible. - * @param xpath xpath of expected WebElement - * @param timeoutSeconds how many seconds we should wait for visibility - * @param errMessage message for TimeoutException - */ - public void waitForDisplayed(String xpath, long timeoutSeconds, String errMessage) { - waitForElement(xpath, timeoutSeconds, errMessage); - WebElement element = driver.findElement(By.xpath(xpath)); - for (int i = 0; i < timeoutSeconds * 10; i++) { - if (element.isDisplayed()) { - return; - } - TimeUtil.sleepSeconds(0.1); - } - throw new TimeoutException(errMessage); - } - - private void waitForElementAction(WebElement webElement, String xpath, long timeoutSeconds, - String errMessage, boolean expected) { - try { - new WebDriverWait(driver, timeoutSeconds) - .until(new Condition(webElement, xpath, expected)); - } catch (TimeoutException e) { - TimeoutException ex = new TimeoutException(errMessage); - ex.initCause(e); - throw ex; - } - } - - /** - * Status of entity that can be shown on Falcon UI. - */ - public enum EntityStatus { - UNKNOWN, SUBMITTED, RUNNING, SUSPENDED - } - - static class Condition implements ExpectedCondition<Boolean> { - - private final boolean isPresent; - private String xpath; - private WebElement webElement; - - public Condition(String xpath, boolean isPresent) { - this.xpath = xpath; - this.isPresent = isPresent; - } - - public Condition(WebElement webElement, String xpath, boolean isPresent) { - this.webElement = webElement; - this.xpath = xpath; - this.isPresent = isPresent; - } - - @Override - public Boolean apply(WebDriver webDriver) { - SearchContext search = (webElement == null) ? webDriver : webElement; - return search.findElements(By.xpath(xpath)).isEmpty() != isPresent; - } - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/ProcessPage.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/ProcessPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/ProcessPage.java deleted file mode 100644 index 36fb1fe..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/pages/ProcessPage.java +++ /dev/null @@ -1,345 +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.falcon.regression.ui.pages; - -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.entity.v0.process.Process; -import org.apache.falcon.regression.core.helpers.ColoHelper; -import org.apache.falcon.regression.core.util.TimeUtil; -import org.apache.log4j.Logger; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.Point; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * Page of a process entity. - */ -public class ProcessPage extends EntityPage<Process> { - - private static final Logger LOGGER = Logger.getLogger(ProcessPage.class); - private boolean isLineageOpened = false; - - private static final String INSTANCES_PANEL = "//div[@id='panel-instance']//span"; - private static final String INSTANCE_STATUS_TEMPLATE = INSTANCES_PANEL + "[contains(..,'%s')]"; - private static final String LINEAGE_LINK_TEMPLATE = - "//a[@class='lineage-href' and @data-instance-name='%s']"; - - //Lineage information xpaths - private static final String CLOSE_LINEAGE_LINK_TEMPLATE = - "//body[@class='modal-open']//button[contains(., 'Close')]"; - private static final String LINEAGE_MODAL = "//div[@id='lineage-modal']"; - private static final String SVG_ELEMENT = "//*[name() = 'svg']/*[name()='g']/*[name()='g']"; - private static final String VERTICES_BLOCKS = SVG_ELEMENT + "[not(@class='lineage-link')]"; - private static final String VERTICES_TEXT = VERTICES_BLOCKS - + "//div[@class='lineage-node-text']"; - private static final String EDGE = SVG_ELEMENT + "[@class='lineage-link']//*[name()='path']"; - private static final String CIRCLE = "//*[name() = 'circle']"; - private static final String VERTICES = VERTICES_BLOCKS + CIRCLE; - private static final String VERTEX_BLOCK_TEMPLATE = VERTICES_BLOCKS + "[contains(., '%s')]"; - private static final String VERTEX_TEMPLATE = VERTEX_BLOCK_TEMPLATE + CIRCLE; - - private static final String LINEAGE_INFO_PANEL_LIST = "//div[@id='lineage-info-panel']" - + "//div[@class='col-md-3']"; - - private static final String LINEAGE_TITLE = LINEAGE_MODAL + "//div[@class='modal-header']/h4"; - - private static final String LINEAGE_LEGENDS_BLOCK = LINEAGE_MODAL - + "//div[@class='modal-body']/div[ul[@class='lineage-legend']]"; - private static final String LINEAGE_LEGENDS_TITLE = LINEAGE_LEGENDS_BLOCK + "/h4"; - private static final String LINEAGE_LEGENDS_ELEMENTS = LINEAGE_LEGENDS_BLOCK + "/ul/li"; - - public ProcessPage(WebDriver driver, ColoHelper helper, String entityName) { - super(driver, helper, EntityType.PROCESS, Process.class, entityName); - } - - /** - * @param nominalTime particular instance of process, defined by it's start time - */ - public void openLineage(String nominalTime) { - waitForElement(String.format(LINEAGE_LINK_TEMPLATE, nominalTime), DEFAULT_TIMEOUT, - "Lineage button didn't appear"); - LOGGER.info("Working with instance: " + nominalTime); - WebElement lineage = - driver.findElement(By.xpath(String.format(LINEAGE_LINK_TEMPLATE, nominalTime))); - LOGGER.info("Opening lineage..."); - lineage.click(); - waitForElement(VERTICES, DEFAULT_TIMEOUT, "Circles not found"); - waitForDisplayed(LINEAGE_TITLE, DEFAULT_TIMEOUT, "Lineage title not found"); - isLineageOpened = true; - } - - public void closeLineage() { - LOGGER.info("Closing lineage..."); - if (isLineageOpened) { - WebElement close = driver.findElement(By.xpath(CLOSE_LINEAGE_LINK_TEMPLATE)); - close.click(); - isLineageOpened = false; - waitForDisappear(CLOSE_LINEAGE_LINK_TEMPLATE, DEFAULT_TIMEOUT, - "Lineage didn't disappear"); - } - } - - @Override - public void refresh() { - super.refresh(); - isLineageOpened = false; - } - - /** - * @return map with instances names and their nominal start time - */ - public HashMap<String, List<String>> getAllVertices() { - LOGGER.info("Getting all vertices from lineage graph..."); - HashMap<String, List<String>> map = null; - if (isLineageOpened) { - waitForElement(VERTICES_TEXT, DEFAULT_TIMEOUT, - "Vertices blocks with names not found"); - List<WebElement> blocks = driver.findElements(By.xpath(VERTICES_TEXT)); - LOGGER.info(blocks.size() + " elements found"); - map = new HashMap<>(); - for (WebElement block : blocks) { - waitForElement(block, ".[contains(.,'/')]", DEFAULT_TIMEOUT, - "Expecting text to contain '/' :" + block.getText()); - String text = block.getText(); - LOGGER.info("Vertex: " + text); - String[] separate = text.split("/"); - String name = separate[0]; - String nominalTime = separate[1]; - if (map.containsKey(name)) { - map.get(name).add(nominalTime); - } else { - List<String> instances = new ArrayList<>(); - instances.add(nominalTime); - map.put(name, instances); - } - } - } - return map; - } - - /** - * @return list of all vertices names - */ - public List<String> getAllVerticesNames() { - LOGGER.info("Getting all vertices names from lineage graph..."); - List<String> list = new ArrayList<>(); - if (isLineageOpened) { - waitForElement(CLOSE_LINEAGE_LINK_TEMPLATE, DEFAULT_TIMEOUT, - "Close Lineage button not found"); - waitForElement(VERTICES_BLOCKS, DEFAULT_TIMEOUT, - "Vertices not found"); - List<WebElement> blocks = driver.findElements(By.xpath(VERTICES_BLOCKS)); - LOGGER.info(blocks.size() + " elements found"); - for (WebElement block : blocks) { - list.add(block.getText()); - } - } - LOGGER.info("Vertices: " + list); - return list; - } - - /** - * Vertex is defined by it's entity name and particular time of it's creation. - */ - public void clickOnVertex(String entityName, String nominalTime) { - LOGGER.info("Clicking on vertex " + entityName + '/' + nominalTime); - if (isLineageOpened) { - WebElement circle = driver.findElement(By.xpath(String.format(VERTEX_TEMPLATE, - entityName + '/' + nominalTime))); - Actions builder = new Actions(driver); - builder.click(circle).build().perform(); - TimeUtil.sleepSeconds(0.5); - } - } - - /** - * @return map of parameters from info panel and their values - */ - public HashMap<String, String> getPanelInfo() { - LOGGER.info("Getting info panel values..."); - HashMap<String, String> map = null; - if (isLineageOpened) { - //check if vertex was clicked - waitForElement(LINEAGE_INFO_PANEL_LIST, DEFAULT_TIMEOUT, "Info panel not found"); - List<WebElement> infoBlocks = driver.findElements(By.xpath(LINEAGE_INFO_PANEL_LIST)); - LOGGER.info(infoBlocks.size() + " values found"); - map = new HashMap<>(); - for (WebElement infoBlock : infoBlocks) { - String text = infoBlock.getText(); - String[] values = text.split("\n"); - map.put(values[0], values[1]); - } - } - LOGGER.info("Values: " + map); - return map; - } - - /** - * @return map of legends as key and their names on UI as values - */ - public HashMap<String, String> getLegends() { - HashMap<String, String> map = null; - if (isLineageOpened) { - map = new HashMap<>(); - List<WebElement> legends = driver.findElements(By.xpath(LINEAGE_LEGENDS_ELEMENTS)); - for (WebElement legend : legends) { - String value = legend.getText(); - String elementClass = legend.getAttribute("class"); - map.put(elementClass, value); - } - } - return map; - } - - /** - * @return the main title of Lineage UI - */ - public String getLineageTitle() { - LOGGER.info("Getting Lineage title..."); - if (isLineageOpened) { - return driver.findElement(By.xpath(LINEAGE_TITLE)).getText(); - } else { - return null; - } - } - - /** - * @return the name of legends block - */ - public String getLegendsTitle() { - LOGGER.info("Getting Legends title..."); - if (isLineageOpened) { - return driver.findElement(By.xpath(LINEAGE_LEGENDS_TITLE)).getText(); - } else { - return null; - } - } - - /** - * @return list of edges present on UI. Each edge presented as two 2d points - beginning and - * the end of the edge. - */ - public List<Point[]> getEdgesFromGraph() { - List<Point[]> pathsEndpoints = null; - LOGGER.info("Getting edges from lineage graph..."); - if (isLineageOpened) { - pathsEndpoints = new ArrayList<>(); - List<WebElement> paths = driver.findElements(By.xpath(EDGE)); - LOGGER.info(paths.size() + " edges found"); - for (WebElement path : paths) { - String[] coordinates = path.getAttribute("d").split("[MLC,]"); - int x = 0, y, i = 0; - while (i < coordinates.length) { - if (!coordinates[i].isEmpty()) { - x = (int) Double.parseDouble(coordinates[i]); - break; - } else { - i++; - } - } - y = (int) Double.parseDouble(coordinates[i + 1]); - Point startPoint = new Point(x, y); - x = (int) Math.round(Double.parseDouble(coordinates[coordinates.length - 2])); - y = (int) Math.round(Double.parseDouble(coordinates[coordinates.length - 1])); - Point endPoint = new Point(x, y); - LOGGER.info("Edge " + startPoint + 'â' + endPoint); - pathsEndpoints.add(new Point[]{startPoint, endPoint}); - } - } - return pathsEndpoints; - } - - /** - * @return common value for radius of every vertex (circle) on the graph - */ - public int getCircleRadius() { - LOGGER.info("Getting value of vertex radius..."); - WebElement circle = driver.findElements(By.xpath(VERTICES)).get(0); - return Integer.parseInt(circle.getAttribute("r")); - } - - /** - * Finds vertex on the graph by its name and evaluates its coordinates as 2d point. - * @param vertex the name of vertex which point is needed - * @return Point(x,y) object - */ - public Point getVertexEndpoint(String vertex) { - /** get circle of start vertex */ - LOGGER.info("Getting vertex coordinates..."); - WebElement block = driver.findElement(By.xpath(String.format(VERTEX_BLOCK_TEMPLATE, vertex))); - String attribute = block.getAttribute("transform"); - attribute = attribute.replaceAll("[a-zA-Z]", ""); - String[] numbers = attribute.replaceAll("[()]", "").split(","); - return new Point(Integer.parseInt(numbers[0]), Integer.parseInt(numbers[1])); - } - - /** - * Returns status of instance from instances panel. - * @param instanceDate date stamp of instance - * @return status of instance from instances panel - */ - public String getInstanceStatus(String instanceDate) { - waitForInstancesPanel(); - LOGGER.info("Getting status of " + instanceDate + " instance"); - List<WebElement> status = - driver.findElements(By.xpath(String.format(INSTANCE_STATUS_TEMPLATE, instanceDate))); - if (status.isEmpty()) { - return null; - } else { - return status.get(0).getAttribute("class").replace("instance-icons instance-link-", ""); - } - } - - /** - * Checks if 'Lineage' link is present on instances panel. - * @param instanceDate date stamp of instance - * @return true if link is present - */ - public boolean isLineageLinkPresent(String instanceDate) { - waitForInstancesPanel(); - LOGGER.info("Checking if 'Lineage' link is present for " + instanceDate); - List<WebElement> lineage = - driver.findElements(By.xpath(String.format(LINEAGE_LINK_TEMPLATE, instanceDate))); - return !lineage.isEmpty(); - } - - private void waitForInstancesPanel() { - waitForElement(INSTANCES_PANEL, DEFAULT_TIMEOUT, "Instances panel didn't appear"); - } - - /** - * Checks whether vertex is terminal or not. - * @param vertexName name of vertex - * @return whether it is terminal or not - */ - public boolean isTerminal(String vertexName) { - LOGGER.info("Checking if " + vertexName + " is 'terminal' instance"); - waitForElement(String.format(VERTEX_TEMPLATE, vertexName), DEFAULT_TIMEOUT, - "Vertex not found"); - WebElement vertex = driver.findElement(By.xpath(String.format(VERTEX_TEMPLATE, vertexName))); - String vertexClass = vertex.getAttribute("class"); - return vertexClass.contains("lineage-node-terminal"); - } -} http://git-wip-us.apache.org/repos/asf/falcon/blob/8e49379d/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java ---------------------------------------------------------------------- diff --git a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java b/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java deleted file mode 100644 index ab73092..0000000 --- a/falcon-regression/merlin/src/main/java/org/apache/falcon/regression/ui/search/AbstractSearchPage.java +++ /dev/null @@ -1,268 +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.falcon.regression.ui.search; - -import com.google.common.util.concurrent.SimpleTimeLimiter; -import com.google.common.util.concurrent.TimeLimiter; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.apache.commons.lang3.tuple.MutablePair; -import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; -import org.apache.falcon.regression.core.util.TimeUtil; -import org.apache.falcon.regression.ui.pages.Page; -import org.apache.log4j.Logger; -import org.openqa.selenium.By; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; -import org.openqa.selenium.support.PageFactory; -import org.openqa.selenium.support.ui.ExpectedCondition; -import org.openqa.selenium.support.ui.Select; -import org.openqa.selenium.support.ui.WebDriverWait; -import org.testng.Assert; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - - -/** Parent page object for all the search ui pages. */ -public abstract class AbstractSearchPage extends Page { - - public static final String UI_URL = MerlinConstants.PRISM_URL; - private static final Logger LOGGER = Logger.getLogger(AbstractSearchPage.class); - public static final int PAGELOAD_TIMEOUT_THRESHOLD = 10; - public static final int ALERT_LIFETIME = 3000; - - public AbstractSearchPage(WebDriver driver) { - super(driver); - waitForAngularToFinish(); - LOGGER.info("Going to initialize Page Header."); - pageHeader = PageFactory.initElements(driver, PageHeader.class); - LOGGER.info("Initialization done."); - } - - private PageHeader pageHeader; - - @FindBy(className = "mainUIView") - protected WebElement mainUI; - - public PageHeader getPageHeader() { - return pageHeader; - } - - protected WebElement getParentElement(WebElement element) { - return element.findElement(By.xpath("..")); - } - - /** - * A rough check to make sure that we are indeed on the correct page. - */ - public abstract void checkPage(); - - // Utility method to enter the data slowly on an element - public static void sendKeysSlowly(WebElement webElement, String data){ - for (String str : data.split("")) { - webElement.sendKeys(str); - } - - } - - public static void clearAndSet(WebElement webElement, String val) { - webElement.clear(); - webElement.sendKeys(val); - } - - public static void clearAndSetSlowly(WebElement webElement, String val) { - webElement.clear(); - sendKeysSlowly(webElement, val); - } - - protected WebElement findElementByNgModel(String ngModelName) { - // trying to get an xpath that looks like: "//*[@ng-model='UIModel.retry.policy']" - final String xpathExpression = "//*[@ng-model='" + ngModelName + "']"; - final List<WebElement> webElements = driver.findElements(By.xpath(xpathExpression)); - Assert.assertEquals(webElements.size(), 1, "Element is not unique for ng-model: " + ngModelName); - return webElements.get(0); - } - - protected void selectNgModelByVisibleText(String ngModelName, String visibleText) { - final WebElement webElement = findElementByNgModel(ngModelName); - final Select select = new Select(webElement); - select.selectByVisibleText(visibleText); - } - - protected void clearAndSetByNgModel(String ngModelName, String value) { - final WebElement webElement = findElementByNgModel(ngModelName); - clearAndSet(webElement, value); - } - - protected void clearAndSetSlowlyByNgModel(String ngModelName, String value) { - final WebElement webElement = findElementByNgModel(ngModelName); - clearAndSetSlowly(webElement, value); - } - - protected void clickById(String id) { - final List<WebElement> webElements = driver.findElements(By.id(id)); - Assert.assertEquals(webElements.size(), 1, "Element is not unique."); - webElements.get(0).click(); - } - - protected void clickByNgModel(String ngModelName) { - final WebElement webElement = findElementByNgModel(ngModelName); - webElement.click(); - } - - // Utility method to get Dropdown Values - public List<String> getDropdownValues(Select element){ - List<WebElement> allOptions = element.getOptions(); - List<String> values = new ArrayList<>(); - for (WebElement option:allOptions){ - values.add(option.getText()); - } - return values; - } - - - protected void waitForAngularToFinish() { - final String javaScript = "return (window.angular != null) && " - + "(angular.element(document).injector() != null) && " - + "(angular.element(document).injector().get('$http').pendingRequests.length === 0)"; - boolean isLoaded = false; - for (int i = 0; i < PAGELOAD_TIMEOUT_THRESHOLD && !isLoaded; i++) { - TimeLimiter timeLimiter = new SimpleTimeLimiter(); - final JavascriptExecutor proxyJsExecutor = - timeLimiter.newProxy((JavascriptExecutor) driver, JavascriptExecutor.class, 10, TimeUnit.SECONDS); - try { - final Object output = proxyJsExecutor.executeScript(javaScript); - isLoaded = Boolean.valueOf(output.toString()); - } catch (Exception e) { - LOGGER.info("Checking of pending request failed because of: " + ExceptionUtils.getFullStackTrace(e)); - } - LOGGER.info(i+1 + ". waiting on angular to finish."); - TimeUtil.sleepSeconds(1); - } - LOGGER.info("angular is done continuing..."); - } - - public String getActiveAlertText() { - if (waitForAlert()) { - waitForAngularToFinish(); - String script = "return $('div.messages.notifs > div:last-child').text();"; - String message = (String)((JavascriptExecutor)driver).executeScript(script); - return message.trim(); - } else { - return null; - } - } - - /** - * Wait for active alert. Check it's lifetime (the period when alert is displayed). - */ - public void validateAlertLifetime() { - final WebElement alertsBlock = driver.findElement(By.xpath("//div[@class='messages notifs']")); - try { - final MutablePair<Long, Long> pair = new MutablePair<>(Long.MAX_VALUE, Long.MAX_VALUE); - // wait 5 seconds for alert to start blinking and record time of first blink - new WebDriverWait(driver, 5, 100).until(new ExpectedCondition<Boolean>() { - @Nullable - @Override - public Boolean apply(WebDriver webDriver) { - String style = alertsBlock.getAttribute("style"); - if ((style.contains("opacity") && !style.contains("opacity: 1;")) - || style.contains("display: block;")) { - pair.setLeft(System.currentTimeMillis()); - return true; - } - return false; - } - }); - // wait 5 seconds for alert to stop blinking and record time of stoppage - for (int i = 0; i < ALERT_LIFETIME + 3000; i += 100) { - String style = alertsBlock.getAttribute("style"); - if (style.contains("display: none;")) { - pair.setRight(Math.min(System.currentTimeMillis(), pair.getRight())); - } else { - pair.setRight(Long.MAX_VALUE); - } - TimeUtil.sleepSeconds(0.1); - } - long diff = pair.getRight() - pair.getLeft(); - LOGGER.info(String.format("Alert was live %d millis.", pair.getRight() - pair.getLeft())); - Assert.assertTrue(ALERT_LIFETIME <= diff, "Alert was present for too short period of time"); - } catch (TimeoutException e) { - Assert.fail("Alert didn't appear in 5 seconds."); - } - } - - /** - * Wait for active alert. - * @return true is alert is present - */ - protected boolean waitForAlert() { - final WebElement alertsBlock = driver.findElement(By.xpath("//div[@class='messages notifs']")); - try { - new WebDriverWait(driver, 5).until(new ExpectedCondition<Boolean>() { - @Nullable - @Override - public Boolean apply(WebDriver webDriver) { - String style = alertsBlock.getAttribute("style"); - return (style.contains("opacity") && !style.contains("opacity: 1;")) - || style.contains("display: block;"); - } - }); - return true; - } catch (TimeoutException e) { - return false; - } - } - - /** - * Performs simple check of element presence. - */ - public WebElement getElementOrNull(String xpath) { - try { - return driver.findElement(By.xpath(xpath)); - } catch (NoSuchElementException ignored) { - return null; - } - } - - - /** - * Method imitates click on check box. If click is not performed method retries the click. - * @param expectedState whether check box is expected to be enabled or not after click. - */ - protected void clickCheckBoxSecurely(WebElement checkBox, boolean expectedState) { - double gap = 0.5; - for (int attempt = 1; attempt <= (DEFAULT_TIMEOUT / gap); attempt++) { - LOGGER.info("Attempt to click a check box: " + attempt); - checkBox.click(); - if (checkBox.isSelected() == expectedState) { - return; - } - TimeUtil.sleepSeconds(gap); - } - Assert.fail("Check box state was not changed even in " + DEFAULT_TIMEOUT + " seconds."); - } - -}
