/*
 * 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 javax.jdo;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.jdo.util.AbstractTest;
import javax.jdo.util.BatchTestRunner;

/**
 * Tests class javax.jdo.Enhancer (Enhancer main class).
 *
 * <p>
 */
public class EnhancerTest extends AbstractTest {

  /** The path delimiter for constructing classpaths. */
  private static final String PATH_DELIMITER = System.getProperty("path.separator");

  /** The maven basedir identifying the directory of the execution environment. */
  private static final String BASEDIR = System.getProperty("basedir");

  /**
   * Main
   *
   * @param args command line arguments
   */
  public static void main(String args[]) {
    BatchTestRunner.run(EnhancerTest.class);
  }

  public void testUsageOption() {
    // invoke enhancer with a usage option
    InvocationResult result = invokeEnhancer("?");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected Usage message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("javax.jdo.Enhancer"));
  }

  public void testHelpOption() {
    // invoke enhancer with a usage option
    InvocationResult result = invokeEnhancer("-help");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected Usage message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("javax.jdo.Enhancer"));
  }

  public void testHOption() {
    // invoke enhancer with a usage option
    InvocationResult result = invokeEnhancer("-h");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected Usage message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("javax.jdo.Enhancer"));
  }

  public void testInvalidOption() {
    // invoke enhancer with an invalid option
    InvocationResult result = invokeEnhancer("-poo");
    assertEquals("Wrong return value ", ENHANCER_USAGE_ERROR, result.getExitValue());
    String errorString = result.getErrorString();
    assertTrue(
        "Expected Usage message from err:\n" + errorString,
        errorString.contains("javax.jdo.Enhancer"));
  }

  public void testProperties() {
    // invoke enhancer with verbose option
    InvocationResult result = invokeEnhancer("-v");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected MockEnhancer vendor message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains(PROPERTY_ENHANCER_VENDOR_NAME));
    assertTrue(
        "Expected MockEnhancer version message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains(PROPERTY_ENHANCER_VERSION_NUMBER));
    assertTrue(
        "Expected MockEnhancer vendor message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("Mock Enhancer"));
    assertTrue(
        "Expected MockEnhancer vendor message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("2.3.0"));
    assertTrue(
        "Expected MockEnhancer properties message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("MockKey"));
  }

  public void testVOption() {
    // invoke enhancer with verbose option
    InvocationResult result = invokeEnhancer("-v");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected Enhancer class message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("javax.jdo.MockEnhancer"));
  }

  public void testVerboseOption() {
    // invoke enhancer with verbose option
    InvocationResult result = invokeEnhancer("-verbose");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected Enhancer class message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("javax.jdo.MockEnhancer"));
  }

  public void testVerboseClasses() {
    // invoke enhancer with .class parameter
    InvocationResult result = invokeEnhancer("-v some.class");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected class message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.class"));
    assertTrue(
        "Expected number of classes from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("1"));
  }

  public void testVerboseJars() {
    // invoke enhancer with a .jar parameter
    InvocationResult result = invokeEnhancer("-v some.jar");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected jar message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jar"));
    assertTrue(
        "Expected number of jars from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("1"));
  }

  public void testVerboseJDOs() {
    // invoke enhancer with a .jdo parameter
    InvocationResult result = invokeEnhancer("-v some.jdo");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected jdo message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jdo"));
    assertTrue(
        "Expected number of jdos from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("1"));
  }

  public void testVerboseAll() {
    // invoke enhancer with multiple parameters
    InvocationResult result = invokeEnhancer("-v some.class some.jar some.jdo");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected jdo message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jdo"));
    assertTrue(
        "Expected jar message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jar"));
    assertTrue(
        "Expected class message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.class"));
    assertTrue(
        "Expected number of elements from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("3"));
  }

  public void testVerboseCheckonlyAll() {
    // invoke enhancer with a checkonly option
    InvocationResult result = invokeEnhancer("-v -checkonly some.class some.jar some.jdo");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected jdo message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jdo"));
    assertTrue(
        "Expected jar message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.jar"));
    assertTrue(
        "Expected class message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some.class"));
    assertTrue(
        "Expected number of elements from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("3"));
  }

  public void testMissingPU() {
    // invoke enhancer with missing parameter
    InvocationResult result = invokeEnhancer("-v -pu");
    assertEquals("Wrong return value ", 3, result.getExitValue());
  }

  public void testVerbosePU() {
    // invoke enhancer with a pu parameter
    InvocationResult result = invokeEnhancer("-v -pu myPU -pu yourPU");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected pu message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("myPU"));
    assertTrue(
        "Expected pu message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("yourPU"));
    assertTrue(
        "Expected number of elements from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("2"));
  }

  public void testClasspath() {
    // invoke enhancer with a classpath parameter
    // JDOHelper must be loadable from this path
    // the File.toURI should append "/" to the path, so only "target/classes" is needed
    InvocationResult result = invokeEnhancer("-v -cp " + BASEDIR + "/target/classes");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected classpath message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("target/classes"));
  }

  public void testBadClasspath() {
    // invoke enhancer with a bad classpath parameter
    // JDOHelper is not loadable from this path
    InvocationResult result = invokeEnhancer("-v -cp target");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 1, result.getExitValue());
    assertTrue(
        "Expected classpath error message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        errorString.contains("JDOHelper"));
  }

  public void testClasspathJar() throws IOException, InterruptedException {
    // invoke enhancer with a classpath parameter
    // JDOHelper must be loadable from this path
    // create the jar file from the target/classes directory
    String uuid = UUID.randomUUID().toString();
    File uuidDir = new File(BASEDIR + "/target/" + uuid);
    uuidDir.mkdirs();
    String enhancerJar = "target/" + uuid + "/enhancer-test.jar";
    String enhancerJarPathname = BASEDIR + "/" + enhancerJar;
    Process create =
        Runtime.getRuntime()
            .exec("jar -cf " + enhancerJarPathname + " -C " + BASEDIR + "/target/classes .");
    int returnCode = create.waitFor();
    assertEquals("jar command returned wrong return code.", 0, returnCode);
    // find the jdo.jar in target
    InvocationResult result = invokeEnhancer("-v -cp " + enhancerJar);
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected classpath message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains(enhancerJar));
  }

  public void testOutputDirectory() {
    // invoke enhancer with an output directory parameter
    InvocationResult result = invokeEnhancer("-v -d some/output/directory");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected directory message from out:\n" + outputString + " with err:\n" + errorString,
        outputString.contains("some/output/directory"));
  }

  public void testMissingOutputDirectory() {
    // invoke enhancer with missing parameter
    InvocationResult result = invokeEnhancer("-v -d");
    assertEquals("Wrong return value ", 3, result.getExitValue());
  }

  public void testDir() {
    // invoke enhancer with directory and not recurse
    InvocationResult result =
        invokeEnhancer("-v " + BASEDIR + "/target/test-classes/enhancer-test-dir");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected directory enhancer-test-dir in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("enhancer-test-dir"));
    assertTrue(
        "Expected file file1.jdo in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file1.jdo"));
    assertTrue(
        "Expected file file2.class in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file2.class"));
    assertTrue(
        "Expected file file3.jar in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file3.jar"));
    assertFalse(
        "Expected no directory enhancer-test-subdir in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("enhancer-test-subdir"));
    assertTrue(
        "Expected 3 files to be enhanced in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("3"));
  }

  public void testDirRecurse() {
    // invoke enhancer with directory and recurse
    InvocationResult result =
        invokeEnhancer("-v -r " + BASEDIR + "/target/test-classes/enhancer-test-dir");
    String outputString = result.getOutputString();
    String errorString = result.getErrorString();
    assertEquals(
        "Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    assertTrue(
        "Expected directory enhancer-test-dir in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("enhancer-test-dir"));
    assertTrue(
        "Expected directory enhancer-test-subdir in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("enhancer-test-subdir"));
    assertTrue(
        "Expected file file1.jdo in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file1.jdo"));
    assertTrue(
        "Expected file file2.class in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file2.class"));
    assertTrue(
        "Expected file file3.jar in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file3.jar"));
    assertTrue(
        "Expected file file4.jdo in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file4.jdo"));
    assertTrue(
        "Expected file file5.class in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file5.class"));
    assertTrue(
        "Expected file file6.jar in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("file6.jar"));
    assertTrue(
        "Expected 6 files to be enhanced in message from out:\n"
            + outputString
            + " with err:\n"
            + errorString,
        outputString.contains("6"));
  }

  private InvocationResult invokeEnhancer(String string) {
    InvocationResult result = new InvocationResult();
    try {
      // create the java command to invoke the Enhancer
      List<String> commands = new ArrayList<>();
      // find the java command in the user's path
      commands.add("java");
      commands.add("-cp");
      commands.add(
          ""
              + BASEDIR
              + "/target/classes"
              + PATH_DELIMITER
              + ""
              + BASEDIR
              + "/target/test-classes");
      commands.add("javax.jdo.Enhancer");
      // add the test options (from the method parameter) to the java command
      String[] optionArray = string.split(" ");
      for (String option : optionArray) {
        commands.add(option);
      }
      String[] cmdarray = commands.toArray(new String[commands.size()]);
      ProcessBuilder builder = new ProcessBuilder(cmdarray);
      Process proc = builder.start();
      InputStream stdout = proc.getInputStream();
      InputStream stderr = proc.getErrorStream();
      CharBuffer outBuffer = CharBuffer.allocate(1000000);
      CharBuffer errBuffer = CharBuffer.allocate(1000000);
      Thread outputThread = createReaderThread(stdout, outBuffer);
      Thread errorThread = createReaderThread(stderr, errBuffer);
      int exitValue = proc.waitFor();
      result.setExitValue(exitValue);
      errorThread.join(10000); // wait ten seconds to get stderr after process terminates
      outputThread.join(10000); // wait ten seconds to get stdout after process terminates
      result.setErrorString(errBuffer.toString());
      result.setOutputString(outBuffer.toString());
      // wait until the Enhancer command finishes
    } catch (InterruptedException ex) {
      throw new RuntimeException("InterruptedException", ex);
    } catch (IOException ex) {
      throw new RuntimeException("IOException", ex);
    } catch (JDOException jdoex) {
      jdoex.printStackTrace();
      Throwable[] throwables = jdoex.getNestedExceptions();
      System.out.println("Exception throwables of size: " + throwables.length);
      for (Throwable throwable : throwables) {
        throwable.printStackTrace();
      }
    }
    return result;
  }

  private Thread createReaderThread(final InputStream input, final CharBuffer output) {
    final Reader reader = new InputStreamReader(input);
    Thread thread =
        new Thread(
            () -> {
              int count = 0;
              int outputBytesRead = 0;
              try {
                while (-1 != (outputBytesRead = reader.read(output))) {
                  count += outputBytesRead;
                }
              } catch (IOException e) {
                e.printStackTrace();
              } finally {
                output.flip();
              }
            });
    thread.start();
    return thread;
  }

  class InvocationResult {
    private int exitValue;
    private String errorString;
    private String outputString;

    int getExitValue() {
      return exitValue;
    }

    private void setExitValue(int exitValue) {
      this.exitValue = exitValue;
    }

    private void setErrorString(String errorString) {
      this.errorString = errorString;
    }

    String getErrorString() {
      return errorString;
    }

    private void setOutputString(String outputString) {
      this.outputString = outputString;
    }

    String getOutputString() {
      return outputString;
    }
  }
}
