All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ack.automate-testassist.1.1.0.source-code.TestSessionRecorder Maven / Gradle / Ivy

Go to download

Library provides classes that Assist the Automate Build plugins to capture Selenium session id and test case names.

There is a newer version: 1.1.1
Show newest version
/*
 * Copyright (c) BrowserStack, Inc. Proprietary content. All rights reserved. Unauthorized use,
 * copies, and derivatives of this file via any medium is strictly prohibited.
 */

package com.browserstack.automate.testassist;

import org.aspectj.lang.JoinPoint;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.HttpCommandExecutor;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


class TestSessionRecorder {

  static boolean DEBUG = System.getProperty("browserstack.automate.debug", "false").equals("true");

  private static final String HUB_BROWSERSTACK_COM =
      System.getProperty("browserstack.automate.hub", "browserstack.com");

  private static final String ENV_BROWSERSTACK_BUILD = "BROWSERSTACK_BUILD";

  private static final String BROWSERSTACK_CAPABILITY_BUILD = "build";

  private static final String OBJECT_CLASS_NAME = Object.class.getCanonicalName();

  // thread-id <-> UnitTestCase[]
  private final Map> testCases;

  // test-case-id <-> test-index
  private final Map testCaseIndices;

  // thread-id <-> sessionId
  private final Map> webDrivers;

  // thread-id <-> last-event-type
  private final Map lastEventType;

  // thread-id <-> sessionId (stale)
  private final Map lastSessionId;

  // sessionId <-> test-id
  private final Map sessionTestMap;

  // Class <-> sessionId
  private final Map clazzSessionMap;

  // Class <-> class-hierarchy
  private final Map> clazzHierarchyMap;

  private final XmlReporter xmlReporter;

  private final Map sessionWebDriverInstanceMap;

  private static class InstanceHolder {
    private static final TestSessionRecorder INSTANCE = new TestSessionRecorder();
  }

  private TestSessionRecorder() {
    testCases = new ConcurrentHashMap>();
    testCaseIndices = new ConcurrentHashMap();
    webDrivers = new ConcurrentHashMap>();
    lastEventType = new ConcurrentHashMap();
    lastSessionId = new ConcurrentHashMap();
    sessionTestMap = new ConcurrentHashMap();
    clazzSessionMap = new ConcurrentHashMap();
    clazzHierarchyMap = new ConcurrentHashMap>();
    xmlReporter = new XmlReporter();
    sessionWebDriverInstanceMap = new ConcurrentHashMap();

    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        try {
          xmlReporter.saveXML();
        } catch (Exception e) {
          if (DEBUG) {
            System.out.println("[ERROR] Failed to save report");
            e.printStackTrace();
          }
        }
      }
    });
  }

  static TestSessionRecorder getInstance() {
    return InstanceHolder.INSTANCE;
  }

  RecordedData findAndRemoveEvent(String key, LinkedList queue) {
    Iterator iterator = queue.iterator();

    while (iterator.hasNext()) {
      RecordedData capturedEvent = iterator.next();
      if (capturedEvent.data.equals(key)) {
        if (DEBUG)
          System.out.println(">>> REMOVE: " + capturedEvent.data + " | Count: " + testCases.size());

        iterator.remove();
        return capturedEvent;
      }
    }

    return null;
  }

  LinkedList getCapturedTestCases() {
    long threadId = Thread.currentThread().getId();
    if (!testCases.containsKey(threadId)) {
      testCases.put(threadId, new LinkedList());
    }

    return testCases.get(threadId);
  }

  LinkedList getCapturedWebDrivers() {
    long threadId = Thread.currentThread().getId();
    if (!webDrivers.containsKey(threadId)) {
      webDrivers.put(threadId, new LinkedList());
    }

    return webDrivers.get(threadId);
  }

  void captureWebDriver(WebDriverInstance webDriverInstance) {
    long threadId = Thread.currentThread().getId();
    if (!webDrivers.containsKey(threadId)) {
      webDrivers.put(threadId, new LinkedList());
    }

    webDrivers.get(threadId).add(webDriverInstance);

    /*
     * Add session id and instance to map for retrieval using sessionId. This is being done because
     * old structure is binded with sessionId.
     */

    sessionWebDriverInstanceMap.put(webDriverInstance.data, webDriverInstance);
  }

  boolean isWebDriverCaptured(WebDriverInstance webDriverInstance) {
    long threadId = Thread.currentThread().getId();
    return webDrivers.containsKey(threadId) && webDrivers.get(threadId).contains(webDriverInstance);
  }

  EventType getLastEventType() {
    long threadId = Thread.currentThread().getId();
    if (lastEventType.containsKey(threadId)) {
      return lastEventType.get(threadId);
    }

    return EventType.UNKNOWN;
  }

  void linkSessionIdToTestCase(String sessionId, UnitTestCase testCase) {
    sessionTestMap.put(sessionId, testCase.data);

    String projectType = ProjectType.AUTOMATE.toString(); // Default
    if (sessionWebDriverInstanceMap.containsKey(sessionId)) {
      projectType = sessionWebDriverInstanceMap.get(sessionId).getProjectType().toString();
    }
    try {
      xmlReporter.appendTest(testCase, sessionId, projectType);
    } catch (Exception e) {
      // ignore?
      if (DEBUG)
        System.out.println("[ERROR] " + e.getMessage());
    }

    if (DEBUG)
      System.out.println(String.format(">>>> LINK: %s <=> %s <<<<", sessionId, testCase));
  }

  Map getSessionTestMap() {
    return sessionTestMap;
  }

  void setLastEventType(EventType eventType) {
    lastEventType.put(Thread.currentThread().getId(), eventType);
  }

  String getLastSessionId() {
    long threadId = Thread.currentThread().getId();
    return lastSessionId.containsKey(threadId) ? lastSessionId.get(threadId) : null;
  }

  void setLastSessionId(String sessionId) {
    lastSessionId.put(Thread.currentThread().getId(), sessionId);
  }

  Long getTestCaseIndex(JoinPoint joinPoint) {
    synchronized (testCaseIndices) {
      String testCaseSignature = joinPoint.getSignature().toLongString();
      Long index =
          testCaseIndices.containsKey(testCaseSignature) ? testCaseIndices.get(testCaseSignature)
              : -1L;
      testCaseIndices.put(testCaseSignature, ++index);
      if (DEBUG)
        System.out.println(String.format("%s => %d", testCaseSignature, index));
      return index;
    }
  }

  String recordClassHierarchy(Object obj) {
    // Stores a list of class names that appear in an object's class hierarchy.
    if (obj == null) {
      return null;
    }

    String clazzCanonicalName = obj.getClass().getCanonicalName();
    if (!clazzHierarchyMap.containsKey(clazzCanonicalName)) {
      Class clazz = obj.getClass();

      List clazzList = new ArrayList();
      while (clazz != null) {
        if (clazz.getCanonicalName().equals(OBJECT_CLASS_NAME)) {
          break;
        }

        clazzList.add(clazz.getCanonicalName());
        clazz = clazz.getSuperclass();
      }

      clazzHierarchyMap.put(clazzCanonicalName, Collections.unmodifiableList(clazzList));
    }

    return clazzCanonicalName;
  }

  String findSessionIdForClass(Object obj) {
    // Returns any previously recorded sessionId for the object.
    // SessionId could have been associated with either the current class or any parent.

    if (obj == null || obj.getClass().getCanonicalName() == null) {
      return null;
    }

    for (String clazzName : clazzHierarchyMap.get(obj.getClass().getCanonicalName())) {
      if (clazzSessionMap.containsKey(clazzName)) {
        return clazzSessionMap.get(clazzName);
      }
    }

    return null;
  }

  void registerSessionIdForCurrentClass(String sessionId) {
    // Each time a webdriver is created, we *try* to record what class it was created in

    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    String clazzName = null;
    for (StackTraceElement st : stackTrace) {
      if (st.isNativeMethod()) {
        break;
      }

      clazzName = st.getClassName();
    }

    if (clazzName != null) {
      clazzSessionMap.put(clazzName, sessionId);
    }
  }


  static String getSignature(JoinPoint joinPoint) {
    return joinPoint.getSignature().toString() + "@" + joinPoint.getTarget().hashCode();
  }

  static void setBuild(DesiredCapabilities capabilities) {
    String build = (String) capabilities.getCapability(BROWSERSTACK_CAPABILITY_BUILD);

    if (build == null || build.trim().length() == 0) {
      String buildTag = System.getenv(ENV_BROWSERSTACK_BUILD);

      if (buildTag != null && buildTag.trim().length() > 0) {
        capabilities.setCapability(BROWSERSTACK_CAPABILITY_BUILD, buildTag.trim());
      }
    }
  }

  static boolean isBrowserStackWebDriver(JoinPoint joinPoint) {
    Object[] constructorArgs = joinPoint.getArgs();
    if (constructorArgs.length > 0) {
      URL hubUrl = null;

      if (constructorArgs[0] instanceof URL) {
        hubUrl = (URL) constructorArgs[0];
      } else if (constructorArgs[0] instanceof HttpCommandExecutor) {
        hubUrl = ((HttpCommandExecutor) constructorArgs[0]).getAddressOfRemoteServer();
      }

      if (hubUrl != null && hubUrl.toString().contains(HUB_BROWSERSTACK_COM)) {
        return true;
      }
    }

    return false;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy