/*
 * 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;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.jdo.Constants;
import javax.jdo.Extent;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalException;
import javax.jdo.JDOFatalInternalException;
import javax.jdo.JDOHelper;
import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.LegacyJava;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class JDO_Test extends TestCase {
  public static final int TRANSIENT = 0;
  public static final int PERSISTENT_NEW = 1;
  public static final int PERSISTENT_CLEAN = 2;
  public static final int PERSISTENT_DIRTY = 3;
  public static final int HOLLOW = 4;
  public static final int TRANSIENT_CLEAN = 5;
  public static final int TRANSIENT_DIRTY = 6;
  public static final int PERSISTENT_NEW_DELETED = 7;
  public static final int PERSISTENT_DELETED = 8;
  public static final int PERSISTENT_NONTRANSACTIONAL = 9;
  public static final int PERSISTENT_NONTRANSACTIONAL_DIRTY = 10;
  public static final int DETACHED_CLEAN = 11;
  public static final int DETACHED_DIRTY = 12;
  public static final int NUM_STATES = 13;
  public static final int ILLEGAL_STATE = 13;

  protected static final String[] states = {
    "transient",
    "persistent-new",
    "persistent-clean",
    "persistent-dirty",
    "hollow",
    "transient-clean",
    "transient-dirty",
    "persistent-new-deleted",
    "persistent-deleted",
    "persistent-nontransactional",
    "persistent-nontransactional-dirty",
    "detached-clean",
    "detached-dirty",
    "illegal"
  };
  private static final int IS_PERSISTENT = 0;
  private static final int IS_TRANSACTIONAL = 1;
  private static final int IS_DIRTY = 2;
  private static final int IS_NEW = 3;
  private static final int IS_DELETED = 4;
  private static final int IS_DETACHED = 5;
  private static final int NUM_STATUSES = 6;

  /*
   * This table indicates the values returned by the status interrogation
   * methods for each state. This is used to determine the current lifecycle
   * state of an object.
   */
  private static final boolean[][] state_statuses = {
    // IS_PERSISTENT IS_TRANSACTIONAL    IS_DIRTY      IS_NEW      IS_DELETED  IS_DETACHED
    // transient
    {false, false, false, false, false, false},

    // persistent-new
    {true, true, true, true, false, false},

    // persistent-clean
    {true, true, false, false, false, false},

    // persistent-dirty
    {true, true, true, false, false, false},

    // hollow
    {true, false, false, false, false, false},

    // transient-clean
    {false, true, false, false, false, false},

    // transient-dirty
    {false, true, true, false, false, false},

    // persistent-new-deleted
    {true, true, true, true, true, false},

    // persistent-deleted
    {true, true, true, false, true, false},

    // persistent-nontransactional
    {true, false, false, false, false, false},

    // persistent-nontransactional-dirty
    {true, false, true, false, false, false},

    // detached_clean
    {false, false, false, false, false, true},

    // detached_dirty
    {false, false, true, false, false, true}
  };

  /** Name of the PersistenceManagerFactoryClass PMF property. */
  public static final String PMF_CLASS_PROP = "javax.jdo.PersistenceManagerFactoryClass";

  /** Name of the ConnectionURL PMF property. */
  public static final String CONNECTION_URL_PROP = "javax.jdo.option.ConnectionURL";

  /** Name of the ConnectionUserName PMF property. */
  public static final String CONNECTION_USERNAME_PROP = "javax.jdo.option.ConnectionUserName";

  /** Name of the ConnectionPassword PMF property. */
  public static final String CONNECTION_PASSWORD_PROP = "javax.jdo.option.ConnectionPassword";

  /** identitytype value for applicationidentity. */
  public static final String APPLICATION_IDENTITY = "applicationidentity";

  /** identitytype value for datastoreidentity. */
  public static final String DATASTORE_IDENTITY = "datastoreidentity";

  /** Map of transaction isolation String values to Integer */
  protected static final Map<String, Integer> levelValues = new HashMap<>();

  static {
    levelValues.put(Constants.TX_READ_UNCOMMITTED, 0);
    levelValues.put(Constants.TX_READ_COMMITTED, 1);
    levelValues.put(Constants.TX_REPEATABLE_READ, 2);
    levelValues.put(Constants.TX_SNAPSHOT, 3);
    levelValues.put(Constants.TX_SERIALIZABLE, 4);
  }

  /**
   * String indicating the type of identity used for the current test case. The value is either
   * "applicationidentity" or "datastoreidentity".
   */
  protected static final String IDENTITYTYPE = System.getProperty("jdo.tck.identitytype");

  /** String indicating the name of the schema for the current test. */
  protected static final String SCHEMANAME = System.getProperty("jdo.tck.schemaname");

  /** Name of the file containing the properties for the PMF. */
  protected static String PMFProperties = System.getProperty("PMFProperties");

  /**
   * Flag indicating whether to clean up data after tests or not. If false then test will not clean
   * up data from database. The default value is true.
   */
  protected static final boolean CLEANUP_DATA =
      System.getProperty("jdo.tck.cleanupaftertest", "true").equalsIgnoreCase("true");

  /** Flag indicating whether to close the PMF after each test or not. It defaults to false. */
  protected static final boolean CLOSE_PMF_AFTER_EACH_TEST =
      System.getProperty("jdo.tck.closePMFAfterEachTest", "false").equalsIgnoreCase("true");

  /** Flag indicating whether to skip JNDI related tests. */
  protected static final boolean SKIP_JNDI =
      System.getProperty("jdo.tck.skipJndi", "false").equalsIgnoreCase("true");

  /** The Properties object for the PersistenceManagerFactory. */
  protected static Properties PMFPropertiesObject;

  /** The PersistenceManagerFactory. */
  protected static PersistenceManagerFactory pmf;

  /** The collection of supported options of the pmf. */
  protected static Collection<String> supportedOptions;

  /** The name of the pmf supported options summary file. */
  private static final String PMF_SUPPORTED_OPTIONS_FILE_NAME = "pmf_supported_options.txt";

  /** The PersistenceManager. */
  protected PersistenceManager pm;

  // Flag indicating successful test run
  protected boolean testSucceeded;

  /** Logger */
  protected final Log logger = LogFactory.getFactory().getInstance("org.apache.jdo.tck");

  /** true if debug logging in enabled. */
  protected final boolean debug = logger.isDebugEnabled();

  /**
   * Indicates an exception thrown in method <code>tearDown</code>. At the end of method <code>
   * tearDown</code> this field is nullified.
   */
  private Throwable tearDownThrowable;

  /**
   * A list of registered oid instances. Corresponding pc instances are deleted in <code>
   * localTearDown</code>.
   */
  private final Collection<Object> tearDownInstances = new LinkedList<>();

  /**
   * A list of registered pc classes. The extents of these classes are deleted in <code>
   * localTearDown</code>.
   */
  private final Collection<Class<?>> tearDownClasses = new LinkedList<>();

  /**
   * Intended for subclasses so that they may skip this class's normal set up procedure.
   *
   * @return true to run normal set up, false to skip normal set up
   */
  protected boolean preSetUp() {
    return true;
  }

  @Override
  protected final void setUp() {
    if (!preSetUp()) {
      return;
    }

    pmf = getPMF();
    localSetUp();
  }

  /**
   * Subclasses may override this method to allocate any data and resources that they need in order
   * to successfully execute this testcase.
   */
  protected void localSetUp() {}

  /**
   * Runs the bare test sequence.
   *
   * @exception Throwable if any exception is thrown
   */
  @Override
  public final void runBare() throws Throwable {
    try {
      testSucceeded = false;
      setUp();
      runTest();
      testSucceeded = true;
    } catch (Throwable e) {
      if (logger.isInfoEnabled()) logger.info("Exception during setUp or runtest: ", e);
      throw e;
    } finally {
      tearDown();
      if (debug) {
        logger.debug("Free memory: " + Runtime.getRuntime().freeMemory());
      }
    }
  }

  /**
   * Sets field <code>tearDownThrowable</code> if it is <code>null</code>. Else, the given throwable
   * is logged using fatal log level.
   *
   * @param throwable the throwable
   */
  private void setTearDownThrowable(String context, Throwable throwable) {
    if (logger.isInfoEnabled()) logger.info("Exception during " + context + ": ", throwable);
    if (this.tearDownThrowable == null) {
      this.tearDownThrowable = throwable;
    }
  }

  /**
   * Intended for subclasses so that they may skip this class's normal tear down procedure.
   *
   * @return true to run normal tear down, false to skip normal tear down
   */
  protected boolean preTearDown() {
    return true;
  }

  /**
   * This method clears data and resources allocated by testcases. It first closes the persistence
   * manager of this testcase. Then it calls method <code>localTearDown</code>. Subclasses may
   * override that method to clear any data and resources that they have allocated in method <code>
   * localSetUp</code>. Finally, this method closes the persistence manager factory.
   *
   * <p><b>Note:</b>These methods are called always, regardless of any exceptions. The first caught
   * exception is kept in field <code>tearDownThrowable</code>. That exception is thrown as a nested
   * exception of <code>JDOFatalException</code> if and only if the testcase executed successful.
   * Otherwise that exception is logged using fatal log level. All other exceptions are logged using
   * fatal log level, always.
   *
   * <p><b>Note:</b>By default, the method tearDown does not close the pmf. This is done at the end
   * of each configuration, unless the property jdo.tck.closePMFAfterEachTest is set to true.
   */
  @Override
  protected final void tearDown() {
    if (!preTearDown()) {
      return;
    }

    try {
      cleanupPM();
    } catch (Throwable t) {
      setTearDownThrowable("cleanupPM", t);
    }

    if ((pmf == null || pmf.isClosed())
        && (this.tearDownInstances.size() > 0 || this.tearDownClasses.size() > 0))
      throw new JDOFatalException(
          "PMF must not be nullified or closed when tear down instances and /or classes have been added.");

    if (pmf != null && pmf.isClosed()) pmf = null;

    try {
      if (CLEANUP_DATA) {
        localTearDown();
      }
    } catch (Throwable t) {
      setTearDownThrowable("localTearDown", t);
    }

    if (CLOSE_PMF_AFTER_EACH_TEST) {
      try {
        closePMF();
      } catch (Throwable t) {
        setTearDownThrowable("closePMF", t);
      }
    }

    if (this.tearDownThrowable != null) {
      Throwable t = this.tearDownThrowable;
      this.tearDownThrowable = null;
      if (testSucceeded) {
        // runTest succeeded, but this method threw exception => error
        throw new JDOFatalException("Exception during tearDown", t);
      }
    }
  }

  /**
   * Deletes all registered pc instances and extents of all registered pc classes. Subclasses may
   * override this method to clear any data and resources that they have allocated in method <code>
   * localSetUp</code>.
   */
  protected void localTearDown() {
    deleteTearDownInstances();
    deleteTearDownClasses();
  }

  protected void addTearDownObjectId(Object oid) {
    // ensure that oid is not a PC instance
    if (JDOHelper.getObjectId(oid) != null || JDOHelper.isTransactional(oid))
      throw new IllegalArgumentException("oid");
    this.tearDownInstances.add(oid);
  }

  protected void addTearDownInstance(Object pc) {
    Object oid = JDOHelper.getObjectId(pc);
    addTearDownObjectId(oid);
  }

  protected void addTearDownClass(Class<?> pcClass) {
    this.tearDownClasses.add(pcClass);
  }

  protected void addTearDownClass(Class<?>[] pcClasses) {
    if (pcClasses == null) return;
    for (Class<?> pcClass : pcClasses) {
      addTearDownClass(pcClass);
    }
  }

  /**
   * Deletes and removes tear down instances. If there are no tear down instances, the this method
   * is a noop. Otherwise, tear down instances are deleted exactly in the order they have been
   * added. Tear down instances are deleted in a separate transaction.
   */
  protected void deleteTearDownInstances() {
    if (this.tearDownInstances.size() > 0) {
      getPM();
      try {
        this.pm.currentTransaction().begin();
        for (Iterator<Object> i = this.tearDownInstances.iterator(); i.hasNext(); ) {
          Object pc;
          try {
            pc = this.pm.getObjectById(i.next(), true);
          } catch (JDOObjectNotFoundException e) {
            pc = null;
          }
          // we only delete those persistent instances
          // which have not been deleted by tests already.
          if (pc != null) {
            this.pm.deletePersistent(pc);
          }
        }
        this.pm.currentTransaction().commit();
      } finally {
        this.tearDownInstances.clear();
        cleanupPM();
      }
    }
  }

  /**
   * Deletes and removes tear down classes. If there are no tear down classes, the this method is a
   * noop. Otherwise, tear down classes are deleted exactly in the order they have been added. Tear
   * down classes are deleted in a separate transaction. Deleting a tear down class means to delete
   * the extent.
   */
  protected void deleteTearDownClasses() {
    if (this.tearDownClasses.size() > 0) {
      getPM();
      try {
        this.pm.currentTransaction().begin();
        for (Class<?> tearDownClass : this.tearDownClasses) {
          this.pm.deletePersistentAll(getAllObjects(this.pm, tearDownClass));
        }
        this.pm.currentTransaction().commit();
      } finally {
        this.tearDownClasses.clear();
        cleanupPM();
      }
    }
  }

  /**
   * Returns a collection of persistence instances of the specified class.
   *
   * @param pm the PersistenceManager
   * @param pcClass the class object of the PersistenceCapabale class
   * @return a Collection of persistence objects
   */
  protected <T> Collection<T> getAllObjects(PersistenceManager pm, Class<T> pcClass) {
    Query<T> query = pm.newQuery(pcClass);
    Extent<T> candidates = null;
    try {
      candidates = pm.getExtent(pcClass, false);
    } catch (JDOException ex) {
      if (debug) logger.debug("Exception thrown for getExtent of class " + pcClass.getName());
      return Collections.emptyList();
    }
    query.setCandidates(candidates);
    return query.executeList();
  }

  /**
   * Get the <code>PersistenceManagerFactory</code> instance for the implementation under test.
   *
   * @return field <code>pmf</code> if it is not <code>null</code>, else sets field <code>pmf</code>
   *     to a new instance and returns that instance.
   */
  protected PersistenceManagerFactory getPMF() {
    if (pmf == null) {
      PMFPropertiesObject = loadProperties(PMFProperties); // will exit here if no properties
      pmf = JDOHelper.getPersistenceManagerFactory(PMFPropertiesObject);
      if (supportedOptions == null) {
        supportedOptions = pmf.supportedOptions();
      }
    }
    return pmf;
  }

  protected Class<?> getPMFClass() {
    if (pmf != null) {
      return pmf.getClass();
    }

    PMFPropertiesObject = loadProperties(PMFProperties);
    String name = PMFPropertiesObject.getProperty(PMF_CLASS_PROP);
    try {
      return Class.forName(name);
    } catch (ClassNotFoundException ex) {
      throw new JDOException("Cannot find PMF class '" + name + "'.", ex);
    }
  }

  /**
   * Get the <code>PersistenceManagerFactory</code> instance for the implementation under test. This
   * method does NOT use the JDOHelper method to retrieve the PMF, instead it creates an instance of
   * the class specified as javax.jdo.PersistenceManagerFactoryClass property. The returned PMF is
   * not configured.
   *
   * @return field <code>pmf</code> if it is not <code>null</code>, else sets field <code>pmf</code>
   *     to a new instance and returns that instance.
   */
  protected PersistenceManagerFactory getUnconfiguredPMF() {
    if (pmf == null) {
      String name = null;
      try {
        Class<?> pmfClass = getPMFClass();
        name = pmfClass.getName();
        pmf = (PersistenceManagerFactory) pmfClass.getDeclaredConstructor().newInstance();
        if (supportedOptions == null) {
          supportedOptions = pmf.supportedOptions();
        }
      } catch (NoSuchMethodException ex) {
        throw new JDOException("No no-args constructor of PMF class '" + name + "'.", ex);
      } catch (InvocationTargetException ex) {
        throw new JDOException("Exception thrown by constructor of PMF class '" + name + "'.", ex);
      } catch (InstantiationException ex) {
        throw new JDOException("Cannot instantiate PMF class '" + name + "'.", ex);
      } catch (IllegalAccessException ex) {
        throw new JDOException(
            "Cannot access PMF class '" + name + "' or its no-arg constructor.", ex);
      }
    }
    return pmf;
  }

  /**
   * Get the <code>PersistenceManager</code> instance for the implementation under test.
   *
   * @return the PersistenceManager
   */
  protected PersistenceManager getPM() {
    if (pm == null) {
      pm = getPMF().getPersistenceManager();
    }
    return pm;
  }

  /**
   * This method cleans up the environment: closes the <code>PersistenceManager</code>. This should
   * avoid leaving multiple PersistenceManager instances around, in case the
   * PersistenceManagerFactory performs PersistenceManager pooling.
   */
  protected void cleanupPM() {
    cleanupPM(pm);
    pm = null;
  }

  /**
   * This method cleans up the specified <code>PersistenceManager</code>. If the pm still has an
   * open transaction, it will be rolled back, before closing the pm.
   *
   * @param pm the PersistenceManager
   */
  protected static void cleanupPM(PersistenceManager pm) {
    if ((pm != null) && !pm.isClosed()) {
      if (pm.currentTransaction().isActive()) {
        pm.currentTransaction().rollback();
      }
      pm.close();
    }
  }

  /** Closes the pmf stored in this instance. */
  public static void closePMF() {
    JDOException failure = null;
    while (pmf != null) {
      try {
        if (!pmf.isClosed()) {
          closePMF(pmf);
        }
        pmf = null;
      } catch (JDOException ex) {
        // store failure of first call pmf.close
        if (failure == null) failure = ex;
        PersistenceManager[] pms = getFailedPersistenceManagers("closePMF", ex);
        for (PersistenceManager persistenceManager : pms) {
          cleanupPM(persistenceManager);
        }
      } catch (RuntimeException ex) {
        pmf = null;
        ex.printStackTrace(System.out);
        throw ex;
      }
    }

    // rethrow JDOException thrown by pmf.close
    if (failure != null) throw failure;
  }

  /**
   * Closes the pmf passed as a parameter. This must be done in a doPrivileged block.
   *
   * @param PMF the PersistenceManagerFactory
   */
  public static void closePMF(final PersistenceManagerFactory PMF) {
    if (PMF != null) {
      if (!PMF.isClosed()) {
        doPrivileged(
            () -> {
              PMF.close();
              return null;
            });
      }
    }
  }

  @SuppressWarnings("unchecked")
  private static <T> T doPrivileged(PrivilegedAction<T> privilegedAction) {
    try {
      return (T) LegacyJava.doPrivilegedAction.invoke(null, privilegedAction);
    } catch (IllegalAccessException | InvocationTargetException e) {
      if (e.getCause() instanceof RuntimeException) {
        throw (RuntimeException) e.getCause();
      }
      throw new JDOFatalInternalException(e.getMessage());
    }
  }

  /**
   * Returns failed PersistenceManagers
   *
   * @param assertionFailure failure
   * @param ex exception
   * @return failed PersistenceManagers
   */
  protected static PersistenceManager[] getFailedPersistenceManagers(
      String assertionFailure, JDOException ex) {
    Throwable[] nesteds = ex.getNestedExceptions();
    int numberOfExceptions = nesteds == null ? 0 : nesteds.length;
    PersistenceManager[] result = new PersistenceManager[numberOfExceptions];
    for (int i = 0; i < numberOfExceptions; ++i) {
      JDOException exc = (JDOException) nesteds[i];
      Object failedObject = exc.getFailedObject();
      if (exc.getFailedObject() instanceof PersistenceManager) {
        result[i] = (PersistenceManager) failedObject;
      } else {
        throw new JDOFatalException(
            assertionFailure,
            "Unexpected failed object of type: " + failedObject.getClass().getName());
      }
    }
    return result;
  }

  /**
   * This method load Properties from a given file.
   *
   * @param fileName the name of the properties file
   * @return a Properties instance with the loaded properties
   */
  protected Properties loadProperties(String fileName) {
    if (fileName == null) {
      fileName = System.getProperty("user.home") + "/.jdo/PMFProperties.properties";
    }
    Properties props = new Properties();
    InputStream propStream = null;
    try {
      propStream = new FileInputStream(fileName);
    } catch (IOException ex) {
      System.out.println("Could not open properties file \"" + fileName + "\"");
      System.out.println(
          "Please specify a system property PMFProperties "
              + "with the PMF properties file name as value "
              + "(defaults to {user.home}/.jdo/PMFProperties.properties)");
      System.exit(1);
    }
    try {
      props.load(propStream);
    } catch (IOException ex) {
      System.out.println("Error loading properties file \"" + fileName + "\"");
      ex.printStackTrace();
      System.exit(1);
    }
    return props;
  }

  /**
   * Prints the specified msg (if debug is true), before it aborts the test case.
   *
   * @param assertionFailure the assertion failure
   * @param msg the message text
   */
  public void fail(String assertionFailure, String msg) {
    if (debug) logger.debug(msg);
    fail(assertionFailure + NL + msg);
  }

  // Helper methods to check for supported options

  /**
   * Dump the supportedOptions to the a file in the specified directory.
   *
   * @param directory the directory the options are dumped to
   */
  public static void dumpSupportedOptions(String directory) {
    if (supportedOptions == null) return;
    File file = new File(directory, PMF_SUPPORTED_OPTIONS_FILE_NAME);
    if (file.exists())
      // PMF supported options have been dumped before => return
      return;
    try (PrintStream resultStream = new PrintStream(new FileOutputStream(file))) {
      for (String supportedOption : supportedOptions) {
        resultStream.println(supportedOption);
      }
    } catch (FileNotFoundException e) {
      throw new JDOFatalException("dumpSupportedOptions: cannot create file " + file.getName(), e);
    }
  }

  /**
   * Prints a message (if debug is true) saying the test with the specified name is not executed,
   * because the JDO implementation under test does not support the specified optional feature.
   *
   * @param testName the name of the test method that is skipped.
   * @param optionalFeature the name of the option not supported by the JDO implementation under
   *     tets.
   */
  protected void printUnsupportedOptionalFeatureNotTested(String testName, String optionalFeature) {
    if (debug) {
      logger.debug(
          "Test "
              + testName
              + " was not run, because optional feature "
              + optionalFeature
              + " is not supported by the JDO implementation under test");
    }
  }

  /**
   * Reports whether TransientTransactional is supported.
   *
   * @return true if TransientTransactional is supported.
   */
  public boolean isTransientTransactionalSupported() {
    return supportedOptions.contains("javax.jdo.option.TransientTransactional");
  }

  /**
   * Reports whether NontransactionalRead is supported.
   *
   * @return true if NontransactionalRead is supported.
   */
  public boolean isNontransactionalReadSupported() {
    return supportedOptions.contains("javax.jdo.option.NontransactionalRead");
  }

  /**
   * Reports whether NontransactionalWrite is supported.
   *
   * @return true if NontransactionalWrite is supported.
   */
  public boolean isNontransactionalWriteSupported() {
    return supportedOptions.contains("javax.jdo.option.NontransactionalWrite");
  }

  /**
   * Reports whether RetainValues is supported.
   *
   * @return true if RetainValues is supported.
   */
  public boolean isRetainValuesSupported() {
    return supportedOptions.contains("javax.jdo.option.RetainValues");
  }

  /**
   * Reports whether Optimistic is supported.
   *
   * @return true if Optimistic is supported.
   */
  public boolean isOptimisticSupported() {
    return supportedOptions.contains("javax.jdo.option.Optimistic");
  }

  /**
   * Reports whether Application Identity is supported.
   *
   * @return true if Application Identity is supported.
   */
  public boolean isApplicationIdentitySupported() {
    return supportedOptions.contains("javax.jdo.option.ApplicationIdentity");
  }

  /**
   * Reports whether Datastore Identity is supported.
   *
   * @return true if Datastore Identity is supported.
   */
  public boolean isDatastoreIdentitySupported() {
    return supportedOptions.contains("javax.jdo.option.DatastoreIdentity");
  }

  /**
   * Reports whether Non-Durable Identity is supported.
   *
   * @return true if Non-Durable Identity is supported.
   */
  public boolean isNonDurableIdentitySupported() {
    return supportedOptions.contains("javax.jdo.option.NonDurableIdentity");
  }

  /**
   * Reports whether an <code>ArrayList</code> collection is supported.
   *
   * @return true if an <code>ArrayList</code> collection is supported.
   */
  public boolean isArrayListSupported() {
    return supportedOptions.contains("javax.jdo.option.ArrayList");
  }

  /**
   * Reports whether a <code>HashMap</code> collection is supported.
   *
   * @return true if a <code>HashMap</code> collection is supported.
   */
  public boolean isHashMapSupported() {
    return supportedOptions.contains("javax.jdo.option.HashMap");
  }

  /**
   * Reports whether a <code>Hashtable</code> collection is supported.
   *
   * @return true if a <code>Hashtable</code> collection is supported.
   */
  public boolean isHashtableSupported() {
    return supportedOptions.contains("javax.jdo.option.Hashtable");
  }

  /**
   * Reports whether a <code>LinkedList</code> collection is supported.
   *
   * @return true if a <code>LinkedList</code> collection is supported.
   */
  public boolean isLinkedListSupported() {
    return supportedOptions.contains("javax.jdo.option.LinkedList");
  }

  /**
   * Reports whether a <code>TreeMap</code> collection is supported.
   *
   * @return true if a <code>TreeMap</code> collection is supported.
   */
  public boolean isTreeMapSupported() {
    return supportedOptions.contains("javax.jdo.option.TreeMap");
  }

  /**
   * Reports whether a <code>TreeSet</code> collection is supported.
   *
   * @return true if a <code>TreeSet</code> collection is supported.
   */
  public boolean isTreeSetSupported() {
    return supportedOptions.contains("javax.jdo.option.TreeSet");
  }

  /**
   * Reports whether a <code>Vector</code> collection is supported.
   *
   * @return true if a <code>Vector</code> collection is supported.
   */
  public boolean isVectorSupported() {
    return supportedOptions.contains("javax.jdo.option.Vector");
  }

  /**
   * Reports whether a <code>Map</code> collection is supported.
   *
   * @return true if a <code>Map</code> collection is supported.
   */
  public boolean isMapSupported() {
    return supportedOptions.contains("javax.jdo.option.Map");
  }

  /**
   * Reports whether a <code>List</code> collection is supported.
   *
   * @return true if a <code>List</code> collection is supported.
   */
  public boolean isListSupported() {
    return supportedOptions.contains("javax.jdo.option.List");
  }

  /**
   * Reports whether arrays are supported.
   *
   * @return true if arrays are supported.
   */
  public boolean isArraySupported() {
    return supportedOptions.contains("javax.jdo.option.Array");
  }

  /**
   * Reports whether a null collection is supported.
   *
   * @return true if a null collection is supported.
   */
  public boolean isNullCollectionSupported() {
    return supportedOptions.contains("javax.jdo.option.NullCollection");
  }

  /**
   * Reports whether Changing Application Identity is supported.
   *
   * @return true if Changing Application Identity is supported.
   */
  public boolean isChangeApplicationIdentitySupported() {
    return supportedOptions.contains("javax.jdo.option.ChangeApplicationIdentity");
  }

  /**
   * Reports whether Binary Compatibility is supported.
   *
   * @return true if Binary Compatibility is supported.
   */
  public boolean isBinaryCompatibilitySupported() {
    return supportedOptions.contains("javax.jdo.option.BinaryCompatibility");
  }

  /**
   * Reports whether UnconstrainedVariables is supported.
   *
   * @return true if UnconstrainedVariables is supported.
   */
  public boolean isUnconstrainedVariablesSupported() {
    return supportedOptions.contains("javax.jdo.query.JDOQL.UnconstraintedQueryVariables");
  }

  /**
   * Reports whether BitwiseOperations is supported.
   *
   * @return true if BitwiseOperations is supported.
   */
  public boolean isBitwiseOperationsSupported() {
    return supportedOptions.contains("javax.jdo.query.JDOQL.bitwiseOperations");
  }

  /**
   * Reports whether SQL queries are supported.
   *
   * @return true if SQL queries are supported.
   */
  public boolean isSQLSupported() {
    return supportedOptions.contains("javax.jdo.query.SQL");
  }

  /**
   * Reports whether getting the DataStoreConnection is supported.
   *
   * @return true if getting the DataStoreConnection is supported.
   */
  public boolean isDataStoreConnectionSupported() {
    return supportedOptions.contains("javax.jdo.option.GetDataStoreConnection");
  }

  /**
   * Reports whether canceling a running query is supported.
   *
   * @return true if canceling a running query is supported.
   */
  public boolean isQueryCancelSupported() {
    return supportedOptions.contains("javax.jdo.option.QueryCancel");
  }

  /**
   * Reports whether setting a Datastore timout is supported.
   *
   * @return true if setting a Datastore timout is supported.
   */
  public boolean isDatastoreTimeoutSupported() {
    return supportedOptions.contains(Constants.OPTION_DATASTORE_TIMEOUT);
  }

  /**
   * Reports whether a feature is supported
   *
   * @param option the option
   * @return true if the specified option is supported
   */
  public boolean isSupported(String option) {
    return supportedOptions.contains(option);
  }

  /**
   * Determine if a class is loadable in the current environment.
   *
   * @param className the name of the class
   * @return true if the class is loadable in the current environment.
   */
  public static boolean isClassLoadable(String className) {
    try {
      Class.forName(className);
      return true;
    } catch (ClassNotFoundException ex) {
      return false;
    }
  }

  /**
   * Determine if the environment is 1.4 version of JRE or better.
   *
   * @return true if 1.4 version of JRE or better.
   */
  public static boolean isJRE14orBetter() {
    return isClassLoadable("java.util.Currency");
  }

  /**
   * This utility method returns a <code>String</code> that indicates the current state of an
   * instance.
   *
   * @param o The object.
   * @return The current state of the instance, by using the <code>JDOHelper</code> state
   *     interrogation methods.
   */
  public static String getStateOfInstance(Object o) {
    boolean existingEntries = false;
    StringBuilder buff = new StringBuilder("{");
    if (JDOHelper.isPersistent(o)) {
      buff.append("persistent");
      existingEntries = true;
    }
    if (JDOHelper.isTransactional(o)) {
      if (existingEntries) buff.append(", ");
      buff.append("transactional");
      existingEntries = true;
    }
    if (JDOHelper.isDirty(o)) {
      if (existingEntries) buff.append(", ");
      buff.append("dirty");
      existingEntries = true;
    }
    if (JDOHelper.isNew(o)) {
      if (existingEntries) buff.append(", ");
      buff.append("new");
      existingEntries = true;
    }
    if (JDOHelper.isDeleted(o)) {
      if (existingEntries) buff.append(", ");
      buff.append("deleted");
    }
    if (JDOHelper.isDetached(o)) {
      if (existingEntries) buff.append(", ");
      buff.append("detached");
    }
    buff.append("}");
    return buff.toString();
  }

  /**
   * This method will return the current lifecycle state of an instance.
   *
   * @param o the object
   * @return the current lifecycle state
   */
  public static int currentState(Object o) {
    boolean[] status = new boolean[NUM_STATUSES];
    status[IS_PERSISTENT] = JDOHelper.isPersistent(o);
    status[IS_TRANSACTIONAL] = JDOHelper.isTransactional(o);
    status[IS_DIRTY] = JDOHelper.isDirty(o);
    status[IS_NEW] = JDOHelper.isNew(o);
    status[IS_DELETED] = JDOHelper.isDeleted(o);
    status[IS_DETACHED] = JDOHelper.isDetached(o);
    int i;
    int j;
    outerloop:
    for (i = 0; i < NUM_STATES; ++i) {
      for (j = 0; j < NUM_STATUSES; ++j) {
        if (status[j] != state_statuses[i][j]) continue outerloop;
      }
      return i;
    }
    return NUM_STATES;
  }

  /**
   * Tests if a found state matches an expected state.
   *
   * @param foundState the found state
   * @param expectedState the expected state
   * @return true if the found state matches the expected state
   */
  public static boolean compareStates(int foundState, int expectedState) {
    // status interrogation gives same values for PERSISTENT_NONTRANSACTIONAL and HOLLOW
    return (expectedState < 0
        || foundState == expectedState
        || (foundState == HOLLOW && expectedState == PERSISTENT_NONTRANSACTIONAL)
        || (foundState == PERSISTENT_NONTRANSACTIONAL && expectedState == HOLLOW));
  }

  /**
   * This method mangles an object by changing all its non-static, non-final fields. It returns true
   * if the object was mangled, and false if there are no fields to mangle.
   *
   * @param oid the oid of the object
   * @return a mangled object
   * @throws Exception exception
   */
  protected boolean mangleObject(Object oid) throws IllegalAccessException {
    Field[] fields = getModifiableFields(oid);
    if (fields.length == 0) return false;
    for (Field field : fields) {
      Class<?> fieldType = field.getType();
      if (fieldType == long.class) {
        field.setLong(oid, 10000L + field.getLong(oid));
      } else if (fieldType == int.class) {
        field.setInt(oid, 10000 + field.getInt(oid));
      } else if (fieldType == short.class) {
        field.setShort(oid, (short) (10000 + field.getShort(oid)));
      } else if (fieldType == byte.class) {
        field.setByte(oid, (byte) (100 + field.getByte(oid)));
      } else if (fieldType == char.class) {
        field.setChar(oid, (char) (10 + field.getChar(oid)));
      } else if (fieldType == String.class) {
        field.set(oid, "This is certainly a challenge" + field.get(oid));
      } else if (fieldType == Integer.class) {
        field.set(oid, Integer.valueOf(10000 + ((Integer) field.get(oid)).intValue()));
      } else if (fieldType == Long.class) {
        field.set(oid, Long.valueOf(10000L + ((Long) field.get(oid)).longValue()));
      } else if (fieldType == Short.class) {
        field.set(oid, Short.valueOf((short) (10000 + ((Short) field.get(oid)).shortValue())));
      } else if (fieldType == Byte.class) {
        field.set(oid, Byte.valueOf((byte) (100 + ((Byte) field.get(oid)).byteValue())));
      } else if (fieldType == Character.class) {
        field.set(oid, Character.valueOf((char) (10 + ((Character) (field.get(oid))).charValue())));
      }
    }
    return true;
  }

  /**
   * Returns modifiable Fields of the class of the parameter. Fields are considered modifiable if
   * they are not static or final. This method requires several permissions in order to run with a
   * SecurityManager, hence the doPrivileged block:
   *
   * <ul>
   *   <li>ReflectPermission("suppressAccessChecks")
   *   <li>RuntimePermission("accessDeclaredMembers")
   * </ul>
   *
   * @param obj the object
   * @return an array of fields
   */
  protected Field[] getModifiableFields(final Object obj) {
    return doPrivileged(
        () -> {
          Class<?> cls = obj.getClass();
          List<Field> result = new ArrayList<>();
          Field[] fields = cls.getFields();
          for (Field field : fields) {
            int modifiers = field.getModifiers();
            if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) continue;
            field.setAccessible(true);
            result.add(field);
          }
          return result.toArray(new Field[result.size()]);
        });
  }

  /**
   * Returns <code>true</code> if the current test runs with application identity. This means the
   * system property jdo.tck.identitytype has the value applicationidentity.
   *
   * @return <code>true</code> if current test runs with application identity; <code>false</code>
   *     otherwise:
   */
  public boolean runsWithApplicationIdentity() {
    return APPLICATION_IDENTITY.equals(IDENTITYTYPE);
  }

  /**
   * Prints a message (if debug is true) saying the test with the specified name is not executed,
   * because the JDO implementation under test is run for an inapplicable identity type.
   *
   * @param testName the name of the test method that is skipped.
   * @param requiredIdentityType the name of the required identity type.
   */
  protected void printNonApplicableIdentityType(String testName, String requiredIdentityType) {
    if (debug) {
      logger.debug(
          "Test "
              + testName
              + " was not run, because it is only applicable for identity type "
              + requiredIdentityType
              + ". The identity type of the current configuration is "
              + IDENTITYTYPE);
    }
  }

  /**
   * Returns the value of the PMF property given by argument <code>key</code>.
   *
   * @param key the key
   * @return the value
   */
  protected String getPMFProperty(String key) {
    return PMFPropertiesObject.getProperty(key);
  }

  /**
   * Returns <code>true</code> if the implementation under test supports all JDO options contained
   * in system property <code>jdo.tck.requiredOptions</code>.
   *
   * @return <code>true</code> if the implementation under test supports all JDO options contained
   *     in system property <code>jdo.tck.requiredOptions</code>
   */
  protected boolean isTestToBePerformed() {
    boolean isTestToBePerformed = true;
    String requiredOptions = System.getProperty("jdo.tck.requiredOptions");
    //        Collection supportedOptions = supportedOptions;
    StringTokenizer tokenizer = new StringTokenizer(requiredOptions, " ,;\n\r\t");
    while (tokenizer.hasMoreTokens()) {
      String requiredOption = tokenizer.nextToken();
      logger.debug("Required option: " + requiredOption);
      if (!requiredOption.equals("") && !supportedOptions.contains(requiredOption)) {
        isTestToBePerformed = false;
        printUnsupportedOptionalFeatureNotTested(getClass().getName(), requiredOption);
      }
    }
    return isTestToBePerformed;
  }

  /** New line. */
  public static final String NL = System.getProperty("line.separator");

  /** A buffer of of error messages. */
  protected static StringBuffer messages;

  /**
   * Appends to error messages.
   *
   * @param message the message
   */
  protected static synchronized void appendMessage(String message) {
    if (messages == null) {
      messages = new StringBuffer(NL);
    }
    messages.append(message);
    messages.append(NL);
  }

  /**
   * Appends to error messages.
   *
   * @param test test option
   * @param context context
   * @param message message
   */
  protected static synchronized void deferredAssertTrue(
      boolean test, String context, String message) {
    if (!test) {
      appendMessage(context + ": " + message);
    }
  }

  /**
   * Appends an error if the actual value does not equal the expected value. Primitive values are
   * autoboxed. Null values are ok for both expected and actual.
   *
   * @param message the message
   * @param expected the expected value
   * @param actual the actual value
   */
  protected void errorIfNotEqual(String message, Object expected, Object actual) {
    if (expected == null) {
      if (actual != null) {
        appendMessage(message + " failed. expected: null; actual: " + actual);
      }
    } else {
      if (!expected.equals(actual)) {
        appendMessage(message + " failed. expected: " + expected + "; actual: " + actual);
      }
    }
  }

  /**
   * Appends an error if the actual value equals the unexpected value. Primitive values are
   * autoboxed. Null values are ok for both unexpected and actual.
   *
   * @param message the message
   * @param unexpected the unexpected value
   * @param actual the actual value
   */
  protected void errorIfEqual(String message, Object unexpected, Object actual) {
    if (unexpected == null) {
      if (actual == null) {
        appendMessage(message + " failed. unexpected: null");
      }
    } else {
      if (unexpected.equals(actual)) {
        appendMessage(message + " failed. unexpected: " + unexpected);
      }
    }
  }

  /**
   * Returns collected error messages, or <code>null</code> if there are none, and clears the
   * buffer.
   *
   * @return collected error messages
   */
  protected static synchronized String retrieveMessages() {
    if (messages == null) {
      return null;
    }
    final String msg = messages.toString();
    messages = null;
    return msg;
  }

  /** Fail the test if there are any error messages. */
  protected void failOnError() {
    String errors = retrieveMessages();
    if (errors != null) {
      fail(errors);
    }
  }

  /**
   * Validate an actual isolation level against the requested level.
   *
   * @param requested requested level
   * @param actual actual level
   * @return true if the actual level is greater or equal the requsted level
   */
  protected boolean validLevelSubstitution(String requested, String actual) {
    int requestedLevel = (levelValues.get(requested)).intValue();
    int actualLevel = (levelValues.get(actual)).intValue();
    return actualLevel >= requestedLevel;
  }
}
