/*
 * 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
<<<<<<< Updated upstream
 *
 *     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
=======
 * 
 *     https://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 
>>>>>>> Stashed changes
 * limitations under the License.
 */

package org.apache.jdo.tck.query.jdoql.methods;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.jdo.JDOQLTypedQuery;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.pc.mylib.MylibReader;
import org.apache.jdo.tck.pc.mylib.PrimitiveTypes;
import org.apache.jdo.tck.pc.mylib.QPrimitiveTypes;
import org.apache.jdo.tck.pc.query.MathSample;
import org.apache.jdo.tck.query.QueryElementHolder;
import org.apache.jdo.tck.query.QueryTest;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Supported Math methods. <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.6.2-48. <br>
 * <B>Assertion Description: </B> Supported Math methods:
 *
 * <ul>
 *   <li>Math.abs(numeric)
 *   <li>Math.sqrt(numeric)
 *   <li>Math.sin(numeric)
 *   <li>Math.cos(numeric)
 *   <li>Math.tan(numeric)
 *   <li>Math.asin(numeric)
 *   <li>Math.acos(numeric)
 *   <li>Math.atan(numeric)
 * </ul>
 */
public class SupportedMathMethods extends QueryTest {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A14.6.2-48 (SupportedMathMethods) failed: ";

  /** */
  private Object oidOfMath1;

  /** */
  private Object oidOfMath2;

  /** */
  private Object oidOfMath3;

  /**
   * The <code>main</code> is called when the class is directly executed from the command line.
   *
   * @param args The arguments passed to the program.
   */
  public static void main(String[] args) {
    BatchTestRunner.run(SupportedMathMethods.class);
  }

  /** */
  public void testAbs0() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.intNotNull.abs().eq(4));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(intNotNull) == 4",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs1() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.intNull.abs().eq(4));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(intNull) == 4",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs2() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.longNotNull.abs().eq(4L));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(longNotNull) == 4",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs3() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.longNull.abs().eq(4L));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(longNull) == 4",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs4() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.floatNotNull.abs().lt(4.1f).and(cand.floatNotNull.abs().gt(3.9f)));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(floatNotNull) < 4.1 &&" + "Math.abs(floatNotNull) > 3.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs5() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.floatNull.abs().lt(4.1f).and(cand.floatNull.abs().gt(3.9f)));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(floatNull) < 4.1 &&" + "Math.abs(floatNull) > 3.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs6() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.doubleNotNull.abs().lt(4.1).and(cand.doubleNotNull.abs().gt(3.9)));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(doubleNotNull) < 4.1 &&" + "Math.abs(doubleNotNull) > 3.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testAbs7() {
    Object expected =
        getTransientMylibInstancesAsList("primitiveTypesPositive", "primitiveTypesNegative");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(cand.doubleNull.abs().lt(4.1).and(cand.doubleNull.abs().gt(3.9)));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "Math.abs(doubleNull) < 4.1 &&" + "Math.abs(doubleNull) > 3.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testSqrt0() {
    Object expected = getTransientMylibInstancesAsList("primitiveTypesPositive");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(
        cand.doubleNotNull
            .gt(0d)
            .and(cand.doubleNotNull.sqrt().lt(2.1).and(cand.doubleNotNull.sqrt().gt(1.9))));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "doubleNotNull > 0 && "
                + "Math.sqrt(doubleNotNull) < 2.1 && "
                + "Math.sqrt(doubleNotNull) > 1.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testSqrt1() {
    Object expected = getTransientMylibInstancesAsList("primitiveTypesPositive");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(
        cand.doubleNull
            .gt(0d)
            .and(cand.doubleNull.sqrt().lt(2.1).and(cand.doubleNull.sqrt().gt(1.9))));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "doubleNull > 0 && "
                + "Math.sqrt(doubleNull) < 2.1 && "
                + "Math.sqrt(doubleNull) > 1.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testSqrt2() {
    Object expected = getTransientMylibInstancesAsList("primitiveTypesPositive");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(
        cand.intNotNull
            .gt(0)
            .and(cand.intNotNull.sqrt().lt(2.1).and(cand.intNotNull.sqrt().gt(1.9))));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "intNotNull > 0 && "
                + "Math.sqrt(intNotNull) < 2.1 && "
                + "Math.sqrt(intNotNull) > 1.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** */
  public void testSqrt3() {
    Object expected = getTransientMylibInstancesAsList("primitiveTypesPositive");

    JDOQLTypedQuery<PrimitiveTypes> query = getPM().newJDOQLTypedQuery(PrimitiveTypes.class);
    QPrimitiveTypes cand = QPrimitiveTypes.candidate();
    query.filter(
        cand.intNull.gt(0).and(cand.intNull.sqrt().lt(2.1).and(cand.intNull.sqrt().gt(1.9))));

    QueryElementHolder<PrimitiveTypes> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ PrimitiveTypes.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "intNull > 0 && "
                + "Math.sqrt(intNull) < 2.1 && "
                + "Math.sqrt(intNull) > 1.9",
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, expected);
  }

  /** Tests for Math.sin() */
  @SuppressWarnings("unchecked")
  public void testSin() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.sin(angle) < 0.02 && Math.sin(angle) > -0.02";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add((MathSample) pm.getObjectById(oidOfMath1));
      expectedResult.add((MathSample) pm.getObjectById(oidOfMath3));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.sin(angle) < 1.02 && Math.sin(angle) > 0.98";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.sin(angle) < -0.98 && Math.sin(angle) > -1.02";
      expectedResult.clear();
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.cos() */
  @SuppressWarnings("unchecked")
  public void testCos() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.cos(angle) < 0.02 && Math.cos(angle) > -0.02";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add((MathSample) pm.getObjectById(oidOfMath2));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.cos(angle) < -0.98 && Math.cos(angle) > -1.02";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.cos(angle) < 1.02 && Math.cos(angle) > 0.98";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.tan() */
  @SuppressWarnings("unchecked")
  public void testTan() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.tan(angle) < 0.02 && Math.tan(angle) > -0.02";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.asin() */
  @SuppressWarnings("unchecked")
  public void testArcSin() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.asin(trigValue) < 0.1 && Math.asin(trigValue) > -0.1";
      List<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.asin(trigValue) < 1.5714 && Math.asin(trigValue) > 1.570";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.asin(trigValue) < -1.570 && Math.asin(trigValue) > -1.5714";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.acos() */
  @SuppressWarnings("unchecked")
  public void testArcCos() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.acos(trigValue) < 1.5714 && Math.acos(trigValue) > 1.570";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.acos(trigValue) < 0.1 && Math.acos(trigValue) > -0.1";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.acos(trigValue) < 3.147 && Math.acos(trigValue) > 3.14";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.atan() */
  @SuppressWarnings("unchecked")
  public void testArcTan() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.atan(trigValue) < 0.5 && Math.atan(trigValue) > -0.5";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add((MathSample) pm.getObjectById(oidOfMath1));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.ceil() */
  @SuppressWarnings("unchecked")
  public void testCeil() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.ceil(doubleValue) == 5";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.ceil(floatValue) == 3";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.ceil(intValue) == 5";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.floor() */
  @SuppressWarnings("unchecked")
  public void testFloor() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.floor(doubleValue) == 4";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath1));
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.floor(floatValue) == 2";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath3));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      filter = "Math.floor(intValue) == 4";
      expectedResult.clear();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.exp() */
  @SuppressWarnings("unchecked")
  public void testExp() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.exp(doubleValue) < 85.63 && Math.exp(doubleValue) > 85.62";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add(pm.getObjectById(MathSample.class, oidOfMath2));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setClass(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** Tests for Math.log() */
  @SuppressWarnings("unchecked")
  public void testLog() {
    insertMathSampleData(getPM());

    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      String filter = "Math.log(doubleValue) < 1.4935 && Math.log(doubleValue) > 1.491";
      Collection<MathSample> expectedResult = new ArrayList<>();
      expectedResult.add((MathSample) pm.getObjectById(oidOfMath2));
      Query<MathSample> q = pm.newQuery(MathSample.class);
      q.setFilter(filter);
      List<MathSample> results = q.executeList();
      checkQueryResultWithoutOrder(ASSERTION_FAILED, filter, results, expectedResult);

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(MylibReader.getTearDownClasses());
    addTearDownClass(MathSample.class);
    loadAndPersistMylib(getPM());
  }

  /** */
  private void insertMathSampleData(PersistenceManager pm) {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      // Sample 1 : angle=PI (180 degrees)
      MathSample ms1 = new MathSample();
      ms1.setId(1);
      ms1.setAngle(new BigDecimal(Math.PI));
      ms1.setTrigValue(new BigDecimal(0.0));
      ms1.setDoubleValue(Double.valueOf(4.55));
      ms1.setFloatValue(Float.valueOf(4.55f));
      ms1.setIntValue(Integer.valueOf(5));
      pm.makePersistent(ms1);

      // Sample 2 : angle=PI/2 (90 degrees)
      MathSample ms2 = new MathSample();
      ms2.setId(2);
      ms2.setAngle(new BigDecimal(Math.PI / 2.0));
      ms2.setTrigValue(new BigDecimal(1.0));
      ms2.setDoubleValue(Double.valueOf(4.45));
      ms2.setFloatValue(Float.valueOf((float) 4.45));
      ms2.setIntValue(Integer.valueOf(4));
      pm.makePersistent(ms2);

      // Sample 3 : angle=0 (0 degrees)
      MathSample ms3 = new MathSample();
      ms3.setId(3);
      ms3.setAngle(new BigDecimal(0));
      ms3.setTrigValue(new BigDecimal(-1.0));
      ms3.setDoubleValue(Double.valueOf(2.49));
      ms3.setFloatValue(Float.valueOf((float) 2.49));
      ms3.setIntValue(Integer.valueOf(3));
      pm.makePersistent(ms3);

      tx.commit();
      oidOfMath1 = pm.getObjectId(ms1);
      oidOfMath2 = pm.getObjectId(ms2);
      oidOfMath3 = pm.getObjectId(ms3);
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }
}
