Package com.opengamma.util.test

Source Code of com.opengamma.util.test.AbstractDbTest

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.util.test;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;

import com.opengamma.lambdava.tuple.Pair;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.ReflectionUtils;
import com.opengamma.util.db.DbConnector;
import com.opengamma.util.db.DbConnectorFactoryBean;
import com.opengamma.util.db.DbDialect;
import com.opengamma.util.db.script.DbSchemaGroupMetadata;
import com.opengamma.util.db.tool.DbDialectUtils;
import com.opengamma.util.db.tool.DbTool;
import com.opengamma.util.db.tool.DbTool.TableCreationCallback;
import com.opengamma.util.time.DateUtils;

/**
* Base DB test.
*/
public abstract class AbstractDbTest implements TableCreationCallback {

  /** Cache. */
  static final Map<String, String> s_databaseTypeVersion = new ConcurrentHashMap<>();
  /** Initialized tools. */
  private static final ConcurrentMap<Pair<String, Class<?>>, DbConnector> s_connectors = new ConcurrentHashMap<>();

  static {
    // initialize the clock
    DateUtils.initTimeZone();
  }

  private final String _databaseType;
  private final String _databaseVersion;
  private volatile DbTool _dbTool;

  //-------------------------------------------------------------------------
  /**
   * Creates an instance.
   *
   * @param databaseType  the database type, not null
   * @param targetVersion  the target version
   */
  protected AbstractDbTest(String databaseType, String targetVersion) {
    ArgumentChecker.notNull(databaseType, "databaseType");
    _databaseType = databaseType;
    _databaseVersion = targetVersion;
  }

  //-------------------------------------------------------------------------
  /**
   * Code run before each subclass.
   * @throws Exception if an error occurs
   */
  @BeforeClass(alwaysRun = true)
  public final void setUpClass() throws Exception {
    doSetUpClass();
  }

  /**
   * Subclasses should override this where necessary and NOT declare @BeforeClass.
   * This handles TestNG behavior better.
   * @throws Exception if an error occurs
   */
  protected void doSetUpClass() throws Exception {
    // override in subclasses
  }

  /**
   * Code run before each test method.
   * Initialize the database to the required version.
   * This tracks the last initialized version in a static map to avoid duplicate
   * DB operations on bigger test classes. This might not be such a good idea.
   */
  @BeforeMethod(alwaysRun = true)
  public final void setUp() throws Exception {
    DbTool dbTool = getDbTool();
    String prevVersion = s_databaseTypeVersion.get(getDatabaseType());
    if ((prevVersion == null) || !prevVersion.equals(getDatabaseVersion())) {
      s_databaseTypeVersion.put(getDatabaseType(), getDatabaseVersion());
      dbTool.setTargetVersion(getDatabaseVersion());
      dbTool.setCreateVersion(getDatabaseVersion());
      dbTool.dropTestSchema();
      dbTool.createTestSchema();
      dbTool.createTestTables(this);
    }
    dbTool.clearTestTables();
    doSetUp();
  }

  /**
   * Subclasses should override this where necessary and NOT declare @BeforeMethod.
   * This handles TestNG behavior better.
   * @throws Exception if an error occurs
   */
  protected void doSetUp() throws Exception {
    // override in subclasses
  }

  /**
   * Code run after each test method.
   * @throws Exception if an error occurs
   */
  @AfterMethod(alwaysRun = true)
  public final void tearDown() throws Exception {
    doTearDown();
    DbTool dbTool = _dbTool;
    if (dbTool != null) {
      dbTool.resetTestCatalog(); // avoids locking issues with Derby
    }
  }

  /**
   * Subclasses should override this where necessary and NOT declare @AfterMethod.
   * This handles TestNG behavior better.
   *
   * @throws Exception if an error occurs
   */
  protected void doTearDown() throws Exception {
    // override in subclasses
  }

  /**
   * Code run after each subclass.
   * @throws Exception if an error occurs
   */
  @AfterClass(alwaysRun = true)
  public void tearDownClass() throws Exception {
    doTearDownClass();
    DbTool dbTool = _dbTool;
    if (dbTool != null) {
      dbTool.resetTestCatalog(); // avoids locking issues with Derby
    }
    _dbTool = null// do not close as we want to retain the data source
  }

  /**
   * Subclasses should override this where necessary and NOT declare @AfterClass.
   * This handles TestNG behavior better.
   *
   * @throws Exception if an error occurs
   */
  protected void doTearDownClass() throws Exception {
    // override in subclasses
  }

  /**
   * Code run after entire suite.
   * @throws Exception if an error occurs
   */
  @AfterSuite(groups = {TestGroup.UNIT_DB, TestGroup.INTEGRATION })
  public static final void tearDownSuite() throws Exception {
    for (DbConnector connector : s_connectors.values()) {
      ReflectionUtils.close(connector);
    }
  }

  //-------------------------------------------------------------------------
  protected String getDatabaseType() {
    return _databaseType;
  }

  protected String getDatabaseVersion() {
    return _databaseVersion;
  }

  //-------------------------------------------------------------------------
  protected DbTool getDbTool() {
    return initDbTool();
  }

  protected DataSourceTransactionManager getTransactionManager() {
    return new DataSourceTransactionManager(getDbTool().getDataSource());
  }

  protected DbConnector getDbConnector() {
    return initConnector();
  }

  /**
   * Override this when enhancing the connector factory.
   *
   * @return a class key to indicate the scope of the enhancement, not null
   */
  protected Class<?> dbConnectorScope() {
    // for subclasses
    return Object.class;
  }

  /**
   * Override this to enhance the connector factory.
   *
   * @param factory  the factory to populate, not null
   */
  protected void initDbConnectorFactory(DbConnectorFactoryBean factory) {
    // for subclasses
  }

  /**
   * Initializes the DBTool outside the constructor.
   * This works better with TestNG and Maven, where the constructor is called
   * even if the test is never run.
   */
  private DbTool initDbTool() {
    DbTool dbTool = _dbTool;
    if (dbTool == null) {
      synchronized (this) {
        dbTool = _dbTool;
        if (dbTool == null) {
          DbConnector connector = s_connectors.get(Pair.<String, Class<?>>of(_databaseType, dbConnectorScope()));
          _dbTool = dbTool = DbTest.createDbTool(_databaseType, connector)// CSIGNORE
        }
      }
    }
    return dbTool;
  }

  private DbConnector initConnector() {
    Class<?> scope = dbConnectorScope();
    Pair<String, Class<?>> key = Pair.<String, Class<?>>of(_databaseType, scope);
    DbConnector connector = s_connectors.get(key);
    if (connector == null) {
      synchronized (this) {
        connector = s_connectors.get(key);
        if (connector == null) {
          DbDialect dbDialect = DbDialectUtils.getSupportedDbDialect(getDatabaseType());
          DbConnectorFactoryBean factory = new DbConnectorFactoryBean();
          factory.setName("DbTest-" + dbDialect.getName() + (scope != null ? "-" + scope.getSimpleName() : ""));
          factory.setDialect(dbDialect);
          factory.setDataSource(getDbTool().getDataSource());
          factory.setTransactionIsolationLevelName("ISOLATION_READ_COMMITTED");
          factory.setTransactionPropagationBehaviorName("PROPAGATION_REQUIRED");
          initDbConnectorFactory(factory);
          connector = factory.createObject();
          s_connectors.put(key, connector);
        }
      }
    }
    return connector;
  }

  //-------------------------------------------------------------------------
  /**
   * Override this if you wish to do something with the database while it is
   * in its "upgrading" state - e.g. populate with test data at a particular
   * version to test the data transformations on the next version upgrades.
   *
   * @param version  the version
   * @param schemaGroupMetadata  the database schema group metadata, not null
   */
  public void tablesCreatedOrUpgraded(final int version, final DbSchemaGroupMetadata schemaGroupMetadata) {
    // No action
  }

  //-------------------------------------------------------------------------
  @Override
  public String toString() {
    return getDatabaseType() + ":" + getDatabaseVersion();
  }

}
TOP

Related Classes of com.opengamma.util.test.AbstractDbTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.