#!/bin/bash
#
# This software is subject to the terms of the Eclipse Public License v1.0
# Agreement, available at the following URL:
# http://www.eclipse.org/legal/epl-v10.html.
# You must accept the terms of that agreement to use this software.
#
# Copyright (C) 2006-2012 Pentaho
# All Rights Reserved.
#
# Script to run the Mondrian test suite under various JDKs, with parameter
# settings, against various RDBMSes. Customize it with your environment -
# whatever JDKs, DBMSes and drivers you have. The script makes lots of
# assumptions about your environment, but you can figure these out by reading
# the code.
#
# This is for mondrian developers & QA. It is not intended to run in a
# release environment.

#ANT_FLAGS=-Dskip.download=true
ANT_FLAGS=
CLEAN=clean
#CLEAN=

# The script's path is $OPEN_DIR/mondrian/bin/megatest; deduce OPEN_DIR.
OPEN_DIR=$(cd $(dirname $0)/../..; pwd)
MONDRIAN_DIR=$(cd $(dirname $0)/..; pwd)
hostname=$(uname -n | cut -d . -f 1)
cygwin=
case $(uname) in
CYGWIN*)
  OPEN_DIR=$(cygpath -m $OPEN_DIR)
  MONDRIAN_DIR=$(cygpath -m $MONDRIAN_DIR)
  cygwin=true
  if [ ${hostname} = mackerel-winxp \
    -a "$OPEN_DIR" = "e:/open" ]; then
    OPEN_DIR=/open
    MONDRIAN_DIR=/open/mondrian
    echo $OPEN_DIR
  fi
  ;;
esac

# Special cases.
case ${hostname} in
mackerel) if [ ! "$cygwin" ]; then hostname=mackerel-linux; fi ;;
esac

case ${hostname} in
branston)
  databaseList="access derby hsqldb mysql oracle"
  jdkList="jdk1.5 jdk1.6"
  ;;
mackerel)
  databaseList="access derby hsqldb"
  jdkList="jdk1.4 jdk1.5 jdk1.6"
  ;;
mackerel-linux)
  databaseList="derby hsqldb"
  jdkList="jdk1.4 jdk1.5 jdk1.6"
  ;;
mackerel-winxp)
  databaseList="access derby hsqldb teradata"
  jdkList="jdk1.4 jdk1.5 jdk1.6"
  ;;
marmalade)
  databaseList="derby hsqldb mysql oracle luciddb postgresql"
  jdkList="jdk1.4 jdk1.5 jdk1.6 openjdk1.6"
  ;;
marmite)
  databaseList="derby hsqldb monetdb mysql oracle"
  jdkList="jdk1.4 jdk1.5 jdk1.6 jdk1.7 openjdk1.6 openjdk1.7 ibmjdk1.6"
  ;;
ATRHisv1)
  databaseList="hsqldb neoview"
  jdkList="jdk1.6"
  ;;
plank)
  databaseList="derby mysql hsqldb"
  jdkList="jdk1.4 jdk1.5 jdk1.6 openjdk1.6"
  ;;
*)
  databaseList="derby hsqldb mysql oracle"
  jdkList="jdk1.4 jdk1.5 jdk1.6"
  ;;
esac

case $(uname) in
CYGWIN*)
  export PS=';'
  ;;
*)
  export PS=':'
  ;;
esac

# Macros to allow groups of properties to be set at once.
export ENABLE_NATIVE="\
    mondrian.native.crossjoin.enable=true \
    mondrian.native.topcount.enable=true \
    mondrian.native.filter.enable=true \
    mondrian.native.nonempty.enable=true"
export DISABLE_NATIVE="\
    mondrian.native.crossjoin.enable=false \
    mondrian.native.topcount.enable=false \
    mondrian.native.filter.enable=false \
    mondrian.native.nonempty.enable=false"
export ENABLE_AGGS="\
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true"
export DISABLE_AGGS="\
    mondrian.rolap.aggregates.Use=false \
    mondrian.rolap.aggregates.Read=false"
export ENABLE_GSETS="\
    mondrian.rolap.groupingsets.enable=true"
export ENABLE_CMCACHE="\
    mondrian.rolap.EnableRolapCubeMemberCache=true"
export ENABLE_SSAS="\
    mondrian.olap.SsasCompatibleNaming=true"
export DISBLE_SSAS="\
    mondrian.olap.SsasCompatibleNaming=false"

doTest() {
  if [ -f test.properties ]; then
    mv test.properties test.properties.bak
  fi
  if [ -f mondrian.properties ]; then
    mv mondrian.properties mondrian.properties.bak
  fi

  doTest2 "$@"

  mv test.properties.bak test.properties
  mv mondrian.properties.bak mondrian.properties
}

doTest2() {
  olap4j=
  mondrian=true
  if [ "$1" = --mondrian ]; then
    mondrian=true
    shift
  fi

  if [ "$1" = --nomondrian ]; then
    mondrian=
    shift
  fi

  if [ "$1" = --olap4j ]; then
    olap4j=true
    shift
  fi

  if [ "$1" = --noolap4j ]; then
    olap4j=
    shift
  fi

  retroweave=
  if [ "$1" = --retroweave ]; then
    retroweave=true
    shift
  fi

  jdk=$1
  database=$2

  # If the database does not exist, silently skip this test.
  database=$2
  if echo "$databaseList" | grep -s "$database"; then
    echo "database $database ok"
  else
    echo "database $database not ok"
    return
  fi

  JAVA_HOME=$(chooseJavaHome $jdk)

  # Use a version of ant (and in particular junit) compatible with the JDK.
  # Some versions of ant don't work on JDK1.4.
  export ANT_HOME=$(chooseAntHome $jdk)

  rm -f megatest.properties
  case $database in
  access)
    (
      jdbcURL=jdbc:odbc:MondrianFoodMart
      jdbcDrivers=sun.jdbc.odbc.JdbcOdbcDriver
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=foodmart;JdbcPassword=foodmart;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  hsqldb)
    (
      jdbcURL=jdbc:hsqldb:file:demo/hsqldb/foodmart
      jdbcDrivers=org.hsqldb.jdbcDriver
      echo driver.classpath=lib/hsqldb.jar
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=sa;JdbcPassword=;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  luciddb)
    (
      export LUCIDDB_HOME=/usr/local/luciddb-0.9.2
      jdbcURL="jdbc:luciddb:http://localhost;schema=FOODMART"
      jdbcDrivers=org.luciddb.jdbc.LucidDbClientDriver
      echo driver.classpath=${LUCIDDB_HOME}/plugin/LucidDbClient.jar
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc='${jdbcURL}';JdbcUser=foodmart;JdbcPassword=foodmart;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  monetdb)
    (
      jdbcURL="jdbc:monetdb://localhost/FOODMART"
      jdbcDrivers=nl.cwi.monetdb.jdbc.MonetDriver
      echo driver.classpath=lib/monetdb-jdbc.jar
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc='${jdbcURL}';JdbcUser=monetdb;JdbcPassword=monetdb;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  neoview)
    (
      jdbcURL='jdbc:hpt4jdbc://${NEOVIEW_HOST_PORT}/:schema=PENTAHO;serverDataSource=PENTAHO_DataSource'
      jdbcUser=${NEOVIEW_USER}
      jdbcPassword=${NEOVIEW_PASSWORD}
      jdbcDrivers=com.hp.t4jdbc.HPT4Driver
      echo driver.classpath=${HOME}/dl/hpt4jdbc.jar
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=${NEOVIEW_USER};JdbcPassword=${NEOVIEW_PASSWORD};Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  oracle)
    (
      #export ORACLE_HOME=G:/oracle/product/10.1.0/Db_1
      driver="$(chooseOracleDriver $jdk)"
      if [ ! -f "$driver" ]; then
        echo "Oracle JDBC driver not found"
        exit 1
      fi
      jdbcURL=jdbc:oracle:thin:foodmart/foodmart@//$(uname -n):1521/XE
      jdbcDrivers=oracle.jdbc.OracleDriver
      echo driver.classpath=${driver}
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo mondrian.foodmart.jdbcUser=foodmart
      echo mondrian.foodmart.jdbcPassword=foodmart
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=foodmart;JdbcPassword=foodmart;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  derby)
    (
      jdbcDrivers=org.apache.derby.jdbc.EmbeddedDriver
      jdbcURL=jdbc:derby:${MONDRIAN_DIR}/demo/derby/foodmart
#     jdbcURL=jdbc:derby:jar:\(demo/derby/derby-foodmart.zip\)/foodmart
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo driver.classpath=${MONDRIAN_DIR}/testlib/derby.jar
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=sa;JdbcPassword=sa;PoolNeeded=false;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  mysql)
    (
      jdbcDrivers=com.mysql.jdbc.Driver
      export jdbcURL='jdbc:mysql://localhost/foodmart?user=foodmart&password=foodmart&characterEncoding=latin1'
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo driver.classpath=/usr/local/mysql-connector-java-3.1.12/mysql-connector-java-3.1.12-bin.jar
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=foodmart;JdbcPassword=foodmart;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  postgresql)
    (
      jdbcDrivers=org.postgresql.Driver
      export jdbcURL='jdbc:postgresql://localhost/foodmart?user=foodmart&password=foodmart'
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo driver.classpath=/usr/share/java/postgresql.jar
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=foodmart;JdbcPassword=foodmart;Catalog=${OPEN_DIR}/mondrian/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  teradata)
    (
      jdbcDrivers=com.ncr.teradata.TeraDriver
      export jdbcURL='jdbc:teradata://localhost/foodmart'
      echo mondrian.foodmart.jdbcURL=${jdbcURL}
      echo mondrian.jdbcDrivers=${jdbcDrivers}
      echo "driver.classpath=${MONDRIAN_DIR}/drivers/terajdbc4.jar${PS}${MONDRIAN_DIR}/drivers/tdgssjava.jar${PS}${MONDRIAN_DIR}/drivers/tdgssconfig.jar"
      echo "mondrian.test.connectString=Provider=mondrian;Jdbc=${jdbcURL};JdbcUser=tduser;JdbcPassword=tduser;Catalog=${MONDRIAN_DIR}/demo/FoodMart.xml;JdbcDrivers=${jdbcDrivers};RoleXX='California manager';"
    ) >> megatest.properties
    ;;
  *) echo "Unknown database $database"; exit 1 ;;
  esac

  shift
  shift


  if [ "$1" = -server ]; then
    shift
  fi

  props=
  for i in $*; do
    echo "$i" >> megatest.properties
    props="$props $i"
    case "$i" in
    mondrian.test.ExpDependencies=*)
      # Expression dependencies requires greater eval depth than the default 3.
      echo "mondrian.rolap.evaluate.MaxEvalDepth=6" >> megatest.properties
      props="$props mondrian.rolap.evaluate.MaxEvalDepth=6"
      ;;
    esac
  done

  cat megatest.properties >> test.properties
  cat megatest.properties >> mondrian.properties

  case $jdk in
  (jdk1.4) retroweave=true ;;
  esac

  echo
  echo "========================================"
  date
  echo "Running test with JDK=$jdk retroweave=$retroweave database=$database props={$props}"
  if [ "$build" ]; then
    echo build=${build}
    if [ "$retroweave" ]; then
      case $jdk in
      jdk1.4)
        # Cannot build or retroweave under 1.4, so switch JDK briefly
        (
          export JAVA_HOME=$(chooseJavaHome jdk1.5)
          export PATH="$JAVA_HOME/bin:$PATH"
          export ANT_HOME=$(chooseAntHome jdk1.5)
          $ANT_HOME/bin/ant $ANT_FLAGS ${CLEAN} all retroweave
        )
        export JAVA_HOME=$(chooseJavaHome jdk1.4)
        export PATH=$JAVA_HOME/bin:$PATH
        ;;
      *)
        $ANT_HOME/bin/ant $ANT_FLAGS ${CLEAN} all retroweave
        ;;
      esac
      if [ "$mondrian" ]; then
        $ANT_HOME/bin/ant $ANT_FLAGS -Dmondrian.retroweave=true test-nobuild
      fi
    else
      export ANT_HOME=$(chooseAntHome $jdk)
      if [ "$mondrian" ]; then
        TEST_TARGET=test-nobuild
      else
        TEST_TARGET=
      fi
      case $database in
      (derby|access)
        $ANT_HOME/bin/ant $ANT_FLAGS ${CLEAN} compile compile.tests unzip-databases ${TEST_TARGET}
        ;;
      (*)
        $ANT_HOME/bin/ant $ANT_FLAGS ${CLEAN} compile compile.tests ${TEST_TARGET}
        ;;
      esac
    fi
  fi

  if [ "$olap4j" ]; then
    (olap4j $jdk mondrian NONE)
    (olap4j $jdk xmla NONE)
    (olap4j $jdk mondrian DBCP)
    (olap4j $jdk xmla DBCP)
  fi
}

# Echoes a value for ANT_HOME consistent with the JDK.
# JDK 1.4 can't run modern versions of ant (because junit requires annotations)
# but retroweaver cannot run on old versions of ant.
chooseAntHome() {
  jdk=$1
  case $jdk in
  jdk1.4)
    case $(uname -o) in
    Cygwin)
      echo $(cd ${OPEN_DIR}/thirdparty/ant; pwd)
      ;;
    *)
      echo $(cd /usr/local/apache-ant-1.6.0; pwd)
    esac
    ;;
  jdk1.5|jdk1.6|jdk1.7|openjdk1.6|openjdk1.7|ibmjdk1.6)
    case $(uname -n) in
    (plank.disruptivetech.com)
      echo /home/jhyde/open/thirdparty/ant;;
    *)
      echo $(cd ${OPEN_DIR}/thirdparty/ant; pwd);;
    esac
    ;;
  esac
}

# Returns the path of a JAVA_HOME for a given JDK version.
chooseJavaHome() {
  jdk=$1
  case ${hostname} in
  (mackerel)
    case $jdk in
    (jdk1.4) echo /c/j2sdk1.4.2_16 ;;
    (jdk1.5) echo /c/jdk1.5.0_14 ;;
    (jdk1.6) echo /c/jdk1.6.0_11 ;;
    (*) echo "Unknown java version $jdk"; exit 1 ;;
    esac;;
  (branston)
    case $jdk in
    (jdk1.5) echo /e/jdk1.5.0_08 ;;
    (jdk1.6) echo /c/jdk1.6.0_01 ;;
    (*) echo "Unknown java version $jdk"; exit 1 ;;
    esac;;
  (mackerel-winxp)
    case $jdk in
    (jdk1.4) echo /e/j2sdk1.4.2_16 ;;
    (jdk1.5) echo /e/jdk1.5.0_14 ;;
    (jdk1.6) echo /e/jdk1.6.0_06 ;;
    (*) echo "Unknown java version $jdk"; exit 1 ;;
    esac;;
  (*)
    if [ -d /usr/lib/jvm/$jdk ]; then
      echo /usr/lib/jvm/$jdk
    elif [ -d /usr/local/$jdk ]; then
      echo /usr/local/$jdk
    else
      echo "Unknown java version $jdk"
      exit 1
    fi
  esac
}

# Returns a path of an Oracle JDBC driver for a given JDK.
# E.g. "/u01/app/oracle/product/11.2.0/jdbc/lib/ojdbc6.jar"
chooseOracleDriver()
{
  for b in "$ORACLE_HOME/jdbc/lib" testlib; do
    case "$jdk" in
    (jdk1.6|openjdk1.6|ibmjdk1.6)
      files="ojdbc6.jar ojdbc5.jar ojdbc14.jar";;
    (jdk1.5)
      files="ojdbc5.jar ojdbc14.jar";;
    (jdk1.4|*)
      files="ojdbc14.jar";;
    esac
    for f in $files; do
      if [ -f "$b/$f" ]; then
        echo "$b/$f"
        return
      fi
    done
  done
}

olap4j() {
  jdk=$1
  driver=$2
  wrapper=$3
  echo
  echo "========================================"
  date
  echo "Running olap4j test with JDK=$jdk driver=$driver wrapper=$wrapper"
  CONNECT_STRING=$(
    awk '
/^mondrian.test.connectString=/ {
  print substr($0, length("mondrian.test.connectString=Provider=mondrian;") + 1)
}       ' megatest.properties)
  DRIVER_CLASSPATH=$(
    awk '
/^driver.classpath=/ {
  print substr($0, length("driver.classpath=") + 1)
}       ' megatest.properties)
  cd ../olap4j
  case $(uname) in
  (Cygwin*) FILE_PREFIX=file:/ ;;
  (*) FILE_PREFIX=file: ;;
  esac
  export ANT_HOME=$(chooseAntHome $jdk)
  $ANT_HOME/bin/ant clean

  case $driver in
  (mondrian)
    echo "org.olap4j.test.connectUrl=jdbc:mondrian:${CONNECT_STRING}"
    echo 'org.olap4j.test.helperClassName=org.olap4j.MondrianTester'
    echo "org.olap4j.test.driverClasspath=${DRIVER_CLASSPATH}"
    echo "org.olap4j.test.wrapper=${wrapper}"
    ;;
  (xmla)
    echo "org.olap4j.test.connectUrl=jdbc:mondrian:${CONNECT_STRING}"
    echo 'org.olap4j.test.helperClassName=org.olap4j.XmlaTester'
    echo "org.olap4j.XmlaTester.CatalogUrl=${FILE_PREFIX}${MONDRIAN_DIR}/demo/FoodMart.xml"
    echo "org.olap4j.test.driverClasspath=${DRIVER_CLASSPATH}"
    echo "org.olap4j.test.wrapper=${wrapper}"
    ;;
  esac > test.properties

  case $jdk in
  (jdk1.4)
    # Cannot build or retroweave under 1.4, so switch JDK briefly
    (
      export JAVA_HOME=$(chooseJavaHome jdk1.5)
      export PATH="$JAVA_HOME/bin:$PATH"
      export ANT_HOME=$(chooseAntHome jdk1.5)
      $ANT_HOME/bin/ant $ANT_FLAGS all retroweave
    )
    export JAVA_HOME=$(chooseJavaHome jdk1.4)
    export PATH=$JAVA_HOME/bin:$PATH
    $ANT_HOME/bin/ant test-nobuild
    ;;
  (*)
    $ANT_HOME/bin/ant $ANT_FLAGS test
    ;;
  esac

  # Javadoc only runs clean under jdk16 or jdk17, because it depends
  # on JDBC 4.0 or later.
  case "$jdk" in
  (jdk1.6|openjdk1.6|jdk1.7|openjdk1.7|ibmjdk1.6) ant javadoc ;;
  esac
}

doLotsOfTests() {
  for agg in true false; do
    for vusers in 1 5; do
      for jdk in $jdkList; do
        for database in $databaseList; do
          for groupingSets in true false; do
            if [ "$nightly" -a $vusers -gt 1 ]; then
              continue
            fi
            # It's a waste of effort to run with grouping sets both true and
            # false if db does not support it.
            if [ "$groupingSets" = false ] ; then
               case "$database" in
               (access|mysql|derby) continue;;
               esac
            fi
            doTest $jdk $database \
                mondrian.test.VUsers=$vusers \
                mondrian.rolap.groupingsets.enable=$agg \
                mondrian.rolap.aggregates.Use=$agg \
                mondrian.rolap.aggregates.Read=$agg
          done
        done
      done
    done
  done
}

doExoticTests() {
  # Test exp dependencies
  doTest jdk1.5 oracle \
    mondrian.test.ExpDependencies=10 \
    mondrian.test.random.seed=-1 \
    mondrian.expCache.enable=false

  rand=$(echo x|awk '{print int(rand() * 65536)}')
  doTest jdk1.5 oracle \
    mondrian.test.ExpDependencies=100 \
    mondrian.test.random.seed=${rand} \
    mondrian.expCache.enable=false

  # Test with exp cache disabled
  doTest jdk1.5 oracle mondrian.expCache.enable=false

  # Test with aggs enabled
  doTest jdk1.5 oracle \
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true

  # Test with aggregate cache disabled
  doTest jdk1.6 oracle mondrian.rolap.star.disableCaching=true

  # Test case-insensitive
  doTest jdk1.6 oracle mondrian.olap.case.sensitive=false

  # Test with cache of RolapCubeMembers disabled.
  doTest jdk1.6 oracle mondrian.rolap.EnableRolapCubeMemberCache=false

  # Retroweave against jdk1.5 and jdk1.6
  doTest --retroweave jdk1.5 oracle
  doTest --retroweave jdk1.6 oracle

  # Configurations which have surfaced bugs
  echo "This test caused a bug"
  doTest jdk1.6 mysql \
    mondrian.native.crossjoin.enable=false \
    mondrian.native.topcount.enable=false \
    mondrian.xmla.drillthroughTotalCount.enable=false \
    mondrian.rolap.LargeDimensionThreshold=1

  echo "This test caused a bug with testDescendantsXxx"
  doTest jdk1.6 oracle \
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true \
    mondrian.rolap.aggregates.ChooseByVolume=true \
    mondrian.rolap.star.disableCaching=true \
    mondrian.native.filter.enable=false \
    mondrian.native.nonempty.enable=false \
    mondrian.xmla.drillthroughTotalCount.enable=false \
    mondrian.olap.fun.crossjoin.optimizer.size=0 \
    mondrian.rolap.groupingsets.enable=true

  echo "This test caused a bug in testNativeSetCaching"
  doTest jdk1.6 oracle \
    mondrian.test.ExpDependencies=10 \
    mondrian.native.crossjoin.enable=false

  echo "This test caused a bug"
  doTest jdk1.6 oracle \
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true \
    mondrian.olap.case.sensitive=false \
    mondrian.test.ExpDependencies=10 \
    mondrian.xmla.drillthroughTotalCount.enable=false \
    mondrian.expCache.enable=false \
    mondrian.rolap.SparseSegmentValueThreshold=25000

  # Caused bug in testFlush
  echo "This test caused a bug in testFlush"
  doTest jdk1.4 mysql \
    mondrian.test.ExpDependencies=10 \
    mondrian.native.crossjoin.enable=false \
    mondrian.xmla.drillthroughTotalCount.enable=false \
    mondrian.rolap.LargeDimensionThreshold=1000 \
    mondrian.rolap.SparseSegmentValueThreshold=10

  echo "This test took more than 3 cycles to load aggs in FunctionTest.testComplexOrExpr"
  doTest jdk1.5 oracle \
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true \
    mondrian.rolap.aggregates.ChooseByVolume=true \
    mondrian.rolap.star.disableCaching=true \
    mondrian.olap.case.sensitive=false \
    mondrian.test.ExpDependencies=10 \
    mondrian.rolap.SparseSegmentValueThreshold=25000

  # Caused bug in testFlush
  echo "This test caused a bug in testFlush"
  doTest jdk1.6 derby \
    mondrian.native.crossjoin.enable=false \
    mondrian.native.topcount.enable=false \
    mondrian.native.nonempty.enable=false \
    mondrian.xmla.drillthroughTotalCount.enable=false

  # Caused lots of out of memory errors towards the end of the test
  echo "This caused out of memory errors"
  doTest --retroweave jdk1.5 oracle \
    mondrian.rolap.aggregates.Use=true \
    mondrian.rolap.aggregates.Read=true \
    mondrian.olap.case.sensitive=false \
    mondrian.test.ExpDependencies=10 \
    mondrian.rolap.evaluate.MaxEvalDepth=6 \
    mondrian.rolap.star.disableCaching=true \
    mondrian.native.topcount.enable=false \
    mondrian.native.filter.enable=false \
    mondrian.native.nonempty.enable=false \
    mondrian.xmla.drillthroughTotalCount.enable=false \
    mondrian.rolap.LargeDimensionThreshold=25000

  echo "Test support for high-cardinality dimensions"
  doTest jdk1.6 oracle \
    mondrian.result.limit=100000 \
    mondrian.result.highCardChunkSize=30
}

# Returns one of its arguments with equal probability
chooseOne() {
  echo "$@" | awk '
{
  srand();
  r = int(rand() * NF) + 1;
  print $r;
}'
  sleep 1s
}

# Prints "true" with a given probability, else "".
# For example, "maybe 0.2" prints "true" 20% of the time.
maybe() {
  echo | awk '{srand(); r = rand(); if (0) print "r=" r ", p=" p; if (r < p) print "true"; else print "";}' p=$1
  sleep 1s
}

doRandom() {
  args=
  jdk="$(chooseOne jdk1.4 jdk1.5 jdk1.6)"
  args="$args $jdk"

  # 20% of the time, run jdk1.5 and jdk1.6 against retrowoven code. jdk1.4
  # is always retrowoven.
  case $jdk in
  (jdk1.5|jdk1.6)
    if [ "$(maybe 0.8 --retroweave)" ]; then
      args="--retroweave $args"
    fi
    ;;
  esac

  args="$args $(chooseOne ${databaseList})"

  # Run JVM in server mode
  if [ "$(maybe 0.3)" ]; then
    args="$args -server"
  fi

  # Test with aggs enabled, and further, choose agg tables by their number of data volume.
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.rolap.aggregates.Use=true mondrian.rolap.aggregates.Read=true"
    if [ "$(maybe 0.5)" ]; then
      args="$args mondrian.rolap.aggregates.ChooseByVolume=true"
    fi
  fi

  # Disable aggregate cache (not with derby - too slow)
  if [ $database != derby -a \
       "$(maybe 0.5)" ]; then
    args="$args mondrian.rolap.star.disableCaching=true"
  fi

  # Test case-insensitive
  if [ "$(maybe 0.3)" ]; then
    args="$args mondrian.olap.case.sensitive=false"
  fi

  # Test expression dependencies.
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.test.ExpDependencies=10"
  fi

  # Test with aggregate cache disabled
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.rolap.star.disableCaching=true"
  fi

  # Test with RolapCubeMember cache disabled
  if [ "$(maybe 0.3)" ]; then
    args="$args mondrian.rolap.EnableRolapCubeMemberCache=false"
  fi

  if [ $(maybe 0.5) ]; then
    # Test with pushdown of NON-EMPTY to SQL disabled
    if [ "$(maybe 0.7)" ]; then
      args="$args mondrian.native.crossjoin.enable=false"
    fi

    # Test with pushdown of TOPCOUNT to SQL disabled
    if [ "$(maybe 0.7)" ]; then
      args="$args mondrian.native.topcount.enable=false"
    fi

    # Test with pushdown of FILTER to SQL disabled
    if [ "$(maybe 0.7)" ]; then
      args="$args mondrian.native.filter.enable=false"
    fi

    # Test with pushdown of Member.Children etc. to SQL disabled
    if [ "$(maybe 0.7)" ]; then
      args="$args mondrian.native.nonempty.enable=false"
    fi
  fi

  if [ "$(maybe 0.4)" ]; then
    args="$args mondrian.xmla.drillthroughTotalCount.enable=false"
  fi

  # Test with expression result cache disabled
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.expCache.enable=false"
  fi

  # Change the threshold for large dimensions from its default value 100.
  if [ "$(maybe 0.4)" ]; then
    args="$args mondrian.rolap.LargeDimensionThreshold=$(chooseOne 1 777 25000)"
  fi

  # Change the threshold for large dimensions from its default value 1000.
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.rolap.SparseSegmentValueThreshold=$(chooseOne 10 25000)"
  fi

  # Change the size at which crossjoins are optimized.
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.olap.fun.crossjoin.optimizer.size=$(chooseOne 0 10 10000)"
  fi

  # Enable GROUPING SETS clause.
  if [ "$(maybe 0.5)" ]; then
    args="$args mondrian.rolap.groupingsets.enable=true"
  fi

  # Different representation of null.
  if [ "$(maybe 0.2)" ]; then
    args="$args mondrian.olap.NullMemberRepresentation=TheNullMember"
  fi

  # Test support for high-cardinality dimensions.
  if [ "$(maybe 0.3)" ]; then
    args="$args mondrian.result.highCardChunkSize=30"
  fi

  doTest $args
}

doQuick() {
  doTest jdk1.7 mysql
}

# Runs the tests that are believed to be working.
doWorking() {
  doTest jdk1.6 oracle ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS}
  doTest jdk1.6 oracle ${ENABLE_NATIVE} ${DISABLE_AGGS} ${ENABLE_SSAS}
  doTest jdk1.6 oracle ${ENABLE_NATIVE} ${ENABLE_AGGS}  ${ENABLE_SSAS}
  doTest jdk1.6 mysql  ${ENABLE_NATIVE} ${ENABLE_AGGS}  ${DISABLE_SSAS}
  doTest jdk1.6 mysql  ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS}
  doTest jdk1.6 mysql  ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS} ${ENABLE_CMCACHE}
  doTest jdk1.6 mysql  ${ENABLE_NATIVE} ${DISABLE_AGGS} ${ENABLE_SSAS}
  doTest jdk1.6 derby  ${ENABLE_NATIVE} ${ENABLE_AGGS}  ${DISABLE_SSAS}
  doTest jdk1.6 derby  ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS}
  doTest jdk1.5 oracle ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS}
  doTest jdk1.4 oracle ${ENABLE_NATIVE} ${DISABLE_AGGS} ${DISABLE_SSAS}
  # not necessarily working
  doTest jdk1.6 oracle ${ENABLE_NATIVE} ${ENABLE_AGGS}
  doTest jdk1.6 oracle ${ENABLE_NATIVE} ${ENABLE_AGGS} ${ENABLE_GSETS}
}

doAllTests() {
  # With olap4j
  doTest --olap4j jdk1.6 oracle
  doTest --olap4j jdk1.5 oracle
  doTest --olap4j jdk1.5 access

  doTest jdk1.6 teradata mondrian.test.VUsers=1
  doTest jdk1.5 teradata mondrian.test.VUsers=1 mondrian.rolap.groupingsets.enable=true
  doTest jdk1.4 teradata mondrian.test.VUsers=1

  doTest --olap4j jdk1.6 postgresql

  # Basic
  doTest jdk1.5 derby mondrian.test.VUsers=1

  doTest jdk1.4 mysql mondrian.test.VUsers=1 mondrian.rolap.aggregates.Use=true mondrian.rolap.aggregates.Read=true
  doTest jdk1.5 mysql mondrian.test.VUsers=1 mondrian.rolap.aggregates.Use=true mondrian.rolap.aggregates.Read=true

  doTest jdk1.4 oracle mondrian.test.VUsers=1
  doTest jdk1.5 oracle mondrian.test.VUsers=1
  doTest jdk1.6 oracle mondrian.test.VUsers=1

  doTest jdk1.5 oracle mondrian.test.ExpDependencies=10 mondrian.test.random.seed=-1 mondrian.expCache.enable=false #mondrian.test.Name=mondrian.test.ParentChildHierarchyTest
  doTest jdk1.5 access mondrian.olap.NullMemberRepresentation= mondrian.test.Class=mondrian.olap.NullMemberRepresentationTest
  doTest jdk1.5 access mondrian.olap.NullMemberRepresentation=\(null\) mondrian.test.Class=mondrian.olap.NullMemberRepresentationTest
  doTest jdk1.5 access mondrian.olap.NullMemberRepresentation=~Missing mondrian.test.Class=mondrian.olap.NullMemberRepresentationTest
  doTest jdk1.5 access mondrian.test.Class=mondrian.rolap.FastBatchingCellReaderTest
  doTest jdk1.5 derby mondrian.test.Class=mondrian.rolap.FastBatchingCellReaderTest
  doTest jdk1.5 mysql mondrian.test.Class=mondrian.rolap.FastBatchingCellReaderTest

#    mondrian.test.Class=mondrian.test.BasicQueryTest
#    mondrian.test.Name=testQueryTimeout


  # Same again, with aggs
  doTest jdk1.5 oracle mondrian.rolap.aggregates.Use=true mondrian.rolap.aggregates.Read=true

  # Same again, non case-sensititive
  doTest jdk1.5 oracle mondrian.olap.case.sensitive=false

  # Do some tests with random configurations
  echo ::: do 3 random tests :::
  for ((k=0; k < 3; k++)) do
    doRandom
  done

  doExoticTests

  # On a Wednesday, do exhaustive tests.
  if [ $(date +%w) = 3 ]; then
    doLotsOfTests
  fi
}

doTests() {
  if [ "$quick" ]; then
    doQuick
  elif [ "$working" ]; then
    doWorking
  elif [ "$random" ]; then
    doRandom
  else
    doAllTests
  fi
}

checkJavadoc() {
  export JAVA_HOME=$(chooseJavaHome jdk1.6)
  export ANT_HOME=$(chooseAntHome jdk1.6)

  $ANT_HOME/bin/ant -emacs javadoc-strict 2>&1 > ant-javadoc.log
  cat ant-javadoc.log |
    grep -e ':[0-9]*: warning' - |
    grep -v -F -f ant-javadoc-expected.log -
}

usage() {
  echo "megatest [--help] [--nightly] [--nobuild] [--quick | --working | --random]"
  echo "Options:"
  echo "  --help     Print this help"
  echo "  --nightly  Run as a nightly batch job, with an error summary"
  echo "  --nobuild  Do not compile code before running the test"
  echo "  --quick    Only run one test"
  echo "  --working  Run the set of tests known to be working 100%"
  echo "  --random   Run a test with a random set of parameters"
}

nightly=
quick=
working=
random=
build=true
while [ $# -gt 0 ]; do
  case "$1" in
  (--help)
    usage
    exit 0
    ;;
  (--nightly)
    nightly=true
    shift
    ;;
  (--quick)
    quick=true
    shift
    ;;
  (--working)
    working=true
    shift
    ;;
  (--random)
    random=true
    shift
    ;;
  (--nobuild)
    build=
    shift
    ;;
  (*)
    break
    ;;
  esac
done

if [ "$nightly" ]; then
  # We're probably called from a cron job. Set up environment.
  cd ${OPEN_DIR}
  . ./env
  cd mondrian

  # Sync latest.
  p4 get ...
  p4 resolve -am

  # Check formatting
  if [ -d ../util ]; then
    p4 get ../util/...
    find . -type f ! -name \*.cup |
      xargs ../util/bin/checkFile
  fi

  # If olap4j exists, sync it
  if [ -d ../olap4j ]; then
    (
    cd ../olap4j
    svn up
    )
  fi
fi

main()
{
  cd "${MONDRIAN_DIR}"
  if [ "$nightly" ]; then
    # If a cron job, run the whole suite before emitting any output.
    buildId="$(uname -n)-$(date +%Y%m%d)-change$(p4 counter change)"
    doTests >megatest.log 2>&1
    echo
    echo "Build $buildId"
    echo http://www.hydromatic.net/buildlogs/mondrian-${buildId}.log.bz2
    echo
    echo ::: Summary :::::::::::::::::::::::::::::::::::::
    echo Tests completed at $(date).
    egrep 'Running test|OK|Tests run| [0-9]*\) ' ./megatest.log
    if egrep 'FAILURE|BUILD FAILED|Failures: [^0]|Errors: [^0]' megatest.log; then
      echo There were failures.
    else
      echo Test succeeded.
    fi

    echo
    echo ::: check javadoc :::::::::::::::::::::::::::::::
    checkJavadoc

    echo
    echo ::: megatest.log :::::::::::::::::::::::::::::::::
    # Limit to 1MB what we show in email. 10MB is gmail's limit.
    head --bytes=1000000 megatest.log
    cp megatest.log /home/jhyde/web/buildlogs/mondrian-${buildId}.log
    bzip2 --best /home/jhyde/web/buildlogs/mondrian-${buildId}.log

  else
    doTests 2>&1 | tee megatest.log
  fi
}

case $(uname) in
CYGWIN*)
  main | dos2unix
  ;;
*)
  main
  ;;
esac

# End megatest
