/*
 * 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
 *
 *     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
 * limitations under the License.
 */
package javax.jdo;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import javax.jdo.util.BatchTestRunner;
import junit.framework.TestSuite;

/** Tests class javax.jdo.JDOHelper for META-INF/jdoconfig.xml compliance. */
public class JDOHelperConfigTest extends AbstractJDOConfigTest implements Constants {

  public static void main(String args[]) {
    BatchTestRunner.run(JDOHelperConfigTest.class);
  }

  /**
   * {@inheritDoc}
   *
   * @return {@inheritDoc}
   */
  public static TestSuite suite() {
    return new TestSuite(JDOHelperConfigTest.class);
  }

  /**
   * Builds up a {@link java.util.Map Map} object that contains key parameter values specific to a
   * named test. All of the properties needed to run a particular test are loaded into this object.
   *
   * @param testVariant the name of the test to include in the {@link java.util.Map Map} values.
   * @param listenerCount the number of life cycle listener class names to add to this map. The
   *     listener names will begin with the value stored in {@link
   *     javax.jdo.Constants.PROPERTY_INSTANCE_LIFECYCLE_LISTENER
   *     PROPERTY_INSTANCE_LIFECYCLE_LISTENER}.
   * @param vendorSpecificPropertyCount the number of properties named of the form
   *     <pre>
   * &quot;property.&quot; + testVariant + &quot;.name&quot;
   * </pre>
   *     that are added to the map.
   * @param excludeName if true the property specified by {@link javax.jdo.Constants.PROPERTY_NAME
   *     PROPERTY_NAME} is not added to the map.
   * @param excludePUName if true the property specified by {@link
   *     javax.jdo.Constants.PROPERTY_PERSISTENCE_UNIT_NAME PROPERTY_PERSISTENCE_UNIT_NAME} is not
   *     added to the map.
   * @return a new {@link java.util.Map Map} object populated with properties that can be used in
   *     this test suite.
   */
  protected Map<String, String> prepareInitialExpectedMap(
      String testVariant,
      int listenerCount,
      int vendorSpecificPropertyCount,
      boolean excludeName,
      boolean excludePUName) {
    Map<String, String> expected = new HashMap<>();

    if (!excludeName) {
      expected.put(PROPERTY_NAME, PMF_ATTRIBUTE_NAME + "." + testVariant);
    }
    if (!excludePUName) {
      expected.put(
          PROPERTY_PERSISTENCE_UNIT_NAME, PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME + "." + testVariant);
    }

    expected.put(
        PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS, PMF_ATTRIBUTE_CLASS + "." + testVariant);
    expected.put(
        PROPERTY_CONNECTION_DRIVER_NAME, PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME + "." + testVariant);
    expected.put(
        PROPERTY_CONNECTION_FACTORY_NAME,
        PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME + "." + testVariant);
    expected.put(
        PROPERTY_CONNECTION_FACTORY2_NAME,
        PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME + "." + testVariant);
    expected.put(
        PROPERTY_CONNECTION_PASSWORD, PMF_ATTRIBUTE_CONNECTION_PASSWORD + "." + testVariant);
    expected.put(PROPERTY_CONNECTION_URL, PMF_ATTRIBUTE_CONNECTION_URL + "." + testVariant);
    expected.put(
        PROPERTY_CONNECTION_USER_NAME, PMF_ATTRIBUTE_CONNECTION_USER_NAME + "." + testVariant);
    expected.put(PROPERTY_IGNORE_CACHE, PMF_ATTRIBUTE_IGNORE_CACHE + "." + testVariant);
    expected.put(PROPERTY_MAPPING, PMF_ATTRIBUTE_MAPPING + "." + testVariant);
    expected.put(PROPERTY_MULTITHREADED, PMF_ATTRIBUTE_MULTITHREADED + "." + testVariant);
    expected.put(
        PROPERTY_NONTRANSACTIONAL_READ, PMF_ATTRIBUTE_NONTRANSACTIONAL_READ + "." + testVariant);
    expected.put(
        PROPERTY_NONTRANSACTIONAL_WRITE, PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE + "." + testVariant);
    expected.put(PROPERTY_OPTIMISTIC, PMF_ATTRIBUTE_OPTIMISTIC + "." + testVariant);
    expected.put(PROPERTY_RESTORE_VALUES, PMF_ATTRIBUTE_RESTORE_VALUES + "." + testVariant);
    expected.put(PROPERTY_RETAIN_VALUES, PMF_ATTRIBUTE_RETAIN_VALUES + "." + testVariant);
    expected.put(
        PROPERTY_DETACH_ALL_ON_COMMIT, PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT + "." + testVariant);
    expected.put(
        PROPERTY_SERVER_TIME_ZONE_ID, PMF_ATTRIBUTE_SERVER_TIME_ZONE_ID + "." + testVariant);

    // listeners
    for (int i = 0; i < listenerCount; i++) {
      expected.put(
          PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER + "listener." + testVariant + ".listener" + i,
          "classes." + testVariant + ".classes" + i);
    }

    // vendor-specific properties
    for (int i = 0; i < vendorSpecificPropertyCount; i++) {
      expected.put(
          "property." + testVariant + ".name" + i, "property." + testVariant + ".value" + i);
    }

    return expected;
  }

  /**
   * Performs a test specified by <tt>testVariantName</tt>, by building up a property map and
   * executing the test according to the property values. With this version of
   * <tt>doPositiveTest</tt> the property name ( {@link javax.jdo.Constants.PROPERTY_NAME
   * PROPERTY_NAME}) and the {@link javax.jdo.Constants.PERSISTENCE_UNIT_NAME
   * PERSISTENCE_UNIT_NAME}) are included in the property map that is used to run the test.
   *
   * @param classpaths class paths to add to the class loader that runs the test that specify where
   *     <tt>jdoconfig.xml</tt> can be found.
   * @param testVariantName the name of the test.
   * @param listenerCount number of listeners utilized in the test.
   * @param vendorSpecificPropertyCount number of vendor properties used in the test.
   * @param checkEqualProperties if true the test's properties are tested.
   * @throws java.io.IOException if an {@java.io.IOException IOException} occurs during class
   *     loading or any part of the test.
   */
  protected void doPositiveTest(
      String[] classpaths,
      String testVariantName,
      int listenerCount,
      int vendorSpecificPropertyCount,
      boolean checkEqualProperties)
      throws IOException {

    doPositiveTest(
        classpaths,
        testVariantName,
        listenerCount,
        vendorSpecificPropertyCount,
        checkEqualProperties,
        false,
        false);
  }

  /**
   * Performs a test specified by <tt>testVariantName</tt>, by building up a property map and
   * executing the test according to the property values. An assertion exeception is thrown if the
   * test being run has a negative (non-true) result. With this version of <tt>doPositiveTest</tt>
   * the property name ({@link javax.jdo.Constants.PROPERTY_NAME PROPERTY_NAME}) and the {@link
   * javax.jdo.Constants.PERSISTENCE_UNIT_NAME PERSISTENCE_UNIT_NAME}) are included in the property
   * map that is used to run the test.
   *
   * @param classpaths class paths to add to the class loader that runs the test that specify where
   *     <tt>jdoconfig.xml</tt> can be found.
   * @param testVariantName the name of the test.
   * @param listenerCount number of listeners utilized in the test.
   * @param vendorSpecificPropertyCount number of vendor properties used in the test.
   * @param checkEqualProperties if true the test's properties are tested.
   * @param excludeName if true the property specified by {@link javax.jdo.Constants.PROPERTY_NAME
   *     PROPERTY_NAME} is not added to the map.
   * @param excludePUName if true the property specified by {@link
   *     javax.jdo.Constants.PROPERTY_PERSISTENCE_UNIT_NAME PROPERTY_PERSISTENCE_UNIT_NAME} is not
   *     added to the map.
   * @throws java.io.IOException if an {@java.io.IOException IOException} occurs during class
   *     loading or any part of the test.
   */
  protected void doPositiveTest(
      String[] classpaths,
      String testVariantName,
      int listenerCount,
      int vendorSpecificPropertyCount,
      boolean checkEqualProperties,
      boolean excludeName,
      boolean excludePUName)
      throws IOException {

    URLClassLoader loader = new JDOConfigTestClassLoader(getClass().getClassLoader(), classpaths);
    Map<String, String> expected =
        prepareInitialExpectedMap(
            testVariantName,
            listenerCount,
            vendorSpecificPropertyCount,
            excludeName,
            excludePUName);
    String name = testVariantName == null ? null : expected.get(PROPERTY_NAME);
    Map<Object, Object> actual = JDOHelper.getPropertiesFromJdoconfig(name, loader);

    assertNotNull("No properties found", actual);
    if (checkEqualProperties) {
      assertEqualProperties(expected, actual);
    }
  }

  public void testPositive00_PMF0_BasicPMFConfigUsingOnlyStandardAttributesAndListeners()
      throws IOException {
    doPositiveTest(
        new String[] {JDOCONFIG_CLASSPATH_PREFIX + "/Positive00"}, "positive00.pmf0", 2, 0, true);
  }

  public void
      testPositive00_PMF1_BasicPMFConfigUsingOnlyPropertyElementsWithStandardJavaxDotJDOProperties()
          throws IOException {
    doPositiveTest(
        new String[] {JDOCONFIG_CLASSPATH_PREFIX + "/Positive00"}, "positive00.pmf1", 2, 0, true);
  }

  public void testPositive00_PMF2_NestedPropertyElementsWithOnlyStandardAttributeNames()
      throws IOException {
    doPositiveTest(
        new String[] {JDOCONFIG_CLASSPATH_PREFIX + "/Positive00"}, "positive00.pmf2", 2, 0, true);
  }

  public void testPositive00_PMF3_StandardAttributesPlusNonstandardPropertiesInPropertyElements()
      throws IOException {
    doPositiveTest(
        new String[] {JDOCONFIG_CLASSPATH_PREFIX + "/Positive00"}, "positive00.pmf3", 2, 2, true);
  }

  public void testPositive00_PMF4_StandardAttributesPlusNonstandardAttributes() throws IOException {
    doPositiveTest(
        new String[] {JDOCONFIG_CLASSPATH_PREFIX + "/Positive00"}, "positive00.pmf4", 0, 2, true);
  }

  public void testPositive01_DuplicatePUsInDifferentConfigFilesButNotRequested()
      throws IOException {
    String[] classpaths =
        new String[] {
          JDOCONFIG_CLASSPATH_PREFIX + "/Positive01/1a",
          JDOCONFIG_CLASSPATH_PREFIX + "/Positive01/1b"
        };
    URLClassLoader loader = new JDOConfigTestClassLoader(getClass().getClassLoader(), classpaths);
    Map<Object, Object> actual =
        JDOHelper.getPropertiesFromJdoconfig(ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, loader);
  }

  public void testPositive02_GetAnonymousPMFWithNoProperties() throws IOException {

    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive02/");

    Map<Object, Object> properties =
        JDOHelper.getPropertiesFromJdoconfig(ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, loader);
    assertNotNull("Anonymous PMF with no properties returned null", properties);
    assertTrue("Anonymous PMF with no properties had properties", properties.size() == 0);
  }

  public void testPositive03_PMF0_PMFClassNameViaServicesLookup() throws IOException {
    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive03/");

    String expected = "class.positive03.pmf0";
    String actual = getPMFClassNameViaServiceLookup(loader);

    assertNotNull("No PMF name found via services lookup", actual);
    assertEquals(expected, actual);
  }

  public void testPositive04_PMF0_PMFClassNameViaServicesLookup() throws IOException {

    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive04/");

    String expected = "class.positive04.pmf0";
    String actual = getPMFClassNameViaServiceLookup(loader);

    assertNotNull("No PMF name found via services lookup", actual);
    assertEquals(expected, actual);
  }

  public void testPositive05_PMF0_PMFClassNameViaServicesLookup() throws IOException {

    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive05/");

    String expected = "class.positive05.pmf0";
    String actual = getPMFClassNameViaServiceLookup(loader);

    assertNotNull("No PMF name found via services lookup", actual);
    assertEquals(expected, actual);
  }

  public void testPositive06_PMF0_GetAnonymousPMFProperties() throws IOException {

    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive06/");

    Map<String, String> expected = prepareInitialExpectedMap("positive06.pmf0", 2, 0, true, true);
    Map<Object, Object> actual =
        JDOHelper.getPropertiesFromJdoconfig(ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, loader);

    assertNotNull("No properties found", actual);
    assertEqualProperties(expected, actual);
  }

  public void testPositive07_PMF0_GetAnonymousPMFPropertiesWithPUName() throws IOException {

    URLClassLoader loader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Positive07/");

    Map<String, String> expected = prepareInitialExpectedMap("positive07.pmf0", 2, 0, true, false);
    Map<Object, Object> actual =
        JDOHelper.getPropertiesFromJdoconfig(ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, loader);

    assertNotNull("No properties found", actual);
    assertEqualProperties(expected, actual);
  }

  public void testNegative00_EmptyJDOConfigXML() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative0/");
      JDOHelper.getPersistenceManagerFactory(loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // sunny day
    }
  }

  public void testNegative01_NoPersistenceUnitsDefined() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative01/");
      JDOHelper.getPersistenceManagerFactory(loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // joy, sweet joy
    }
  }

  public void testNegative02_DuplicateAnonymousPersistenceUnitsInSameConfig() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative02/");
      JDOHelper.getPersistenceManagerFactory(loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // the cockles of my heart warmeth
    }
  }

  public void testNegative03_DuplicateNamedPersistenceUnitsInSameConfig() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative03/");
      JDOHelper.getPersistenceManagerFactory("name.negative03", loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // warm fuzzies
    }
  }

  public void testNegative04_DuplicatePUNamePropertyInAttributeAndElement() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative04/");
      JDOHelper.getPersistenceManagerFactory("name.negative04.value0", loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // no cold pricklies
    }
  }

  public void testNegative05_DuplicatePropertyInAttributeAndElement() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative05/");
      JDOHelper.getPersistenceManagerFactory(loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // party!
    }
  }

  public void testNegative06_DuplicatePUInDifferentConfigFiles() throws IOException {
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(),
              JDOCONFIG_CLASSPATH_PREFIX + "/Negative06/6a/",
              JDOCONFIG_CLASSPATH_PREFIX + "/Negative06/6b/");
      JDOHelper.getPersistenceManagerFactory("name.negative06", loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // clear blue sky
    }
  }

  public void testNegative07_EmptyServicesFile() throws IOException {
    JDOConfigTestClassLoader testLoader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative07/");
    String shouldBeNull = getPMFClassNameViaServiceLookup(testLoader);
    assertNull(shouldBeNull);
  }

  public void testNegative08_NoResourcesFound() {
    String resource = "" + RANDOM.nextLong();
    InputStream in = getClass().getClassLoader().getResourceAsStream(resource);
    assertNull(in);

    // resource pretty much guaranteed not to exist
    try {
      JDOHelper.getPersistenceManagerFactory(resource);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalUserException x) {
      // happy path
    }
  }

  public void testNegative08_ServicesFileWithOnlyComments() throws IOException {
    JDOConfigTestClassLoader testLoader =
        new JDOConfigTestClassLoader(
            getClass().getClassLoader(), JDOCONFIG_CLASSPATH_PREFIX + "/Negative08/");
    String shouldBeNull = getPMFClassNameViaServiceLookup(testLoader);
    assertNull(shouldBeNull);
  }

  public void testNegative09_MultipleInvalidClassesInDifferentServicesFiles() throws IOException {

    // no class name in Negative09/jdoconfig.xml
    // 9a and 9b include services/javax.jdo.PersistenceManagerFactory
    // with bad implementations
    try {
      URLClassLoader loader =
          new JDOConfigTestClassLoader(
              getClass().getClassLoader(),
              JDOCONFIG_CLASSPATH_PREFIX + "/Negative09/9a/",
              JDOCONFIG_CLASSPATH_PREFIX + "/Negative09/9b/",
              TEST_CLASSPATH,
              API_CLASSPATH);
      JDOHelper.getPersistenceManagerFactory("name.negative09", loader);
      fail("JDOHelper failed to throw JDOFatalUserException");
    } catch (JDOFatalException x) {
      Throwable[] nestedExceptions = x.getNestedExceptions();
      if (nestedExceptions.length != 2) {
        appendMessage(
            "JDOHelper.getPersistenceManagerFactory wrong number of "
                + "nested exceptions. Expected 2, got "
                + nestedExceptions.length
                + "\n"
                + x);
      }
      for (int i = 0; i < nestedExceptions.length; ++i) {
        Throwable exception = nestedExceptions[i];
        if (!(exception instanceof JDOFatalException)) {
          appendMessage(
              "Nested exception "
                  + exception.getClass().getName()
                  + " is not a JDOFatalException.");
        }
      }
    }
    failOnError();
  }
}
