    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package javax.jdo;
    19
    20  import java.io.File;
    21  import java.io.IOException;
    22  import java.io.InputStream;
    23  import java.io.InputStreamReader;
    24  import java.io.Reader;
    25  import java.nio.CharBuffer;
    26  import java.util.ArrayList;
    27  import java.util.List;
    28  import java.util.UUID;
    29
    30  import javax.jdo.util.AbstractTest;
    31  import javax.jdo.util.BatchTestRunner;
    32
    33
    34  /**
    35   * Tests class javax.jdo.Enhancer (Enhancer main class).
    36   * <p>
    37   */
    38  public class EnhancerTest extends AbstractTest {
    39
    40      /** The path delimiter for constructing classpaths. */
    41      private static String pathDelimiter = System.getProperty("path.separator");
    42
    43      /** The maven basedir identifying the directory of the execution environment. */
    44      private static String basedir = System.getProperty("basedir");
    45
    46      /** */
    47      public static void main(String args[]) {
    48          BatchTestRunner.run(EnhancerTest.class);
    49      }
    50
    51      public void testUsageOption() {
    52          // invoke enhancer with a usage option
    53          InvocationResult result = invokeEnhancer("?");
    54          String outputString = result.getOutputString();
    55          String errorString = result.getErrorString();
    56          assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    57          assertTrue("Expected Usage message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("javax.jdo.Enhancer"));
    58      }
    59
    60      public void testHelpOption() {
    61          // invoke enhancer with a usage option
    62          InvocationResult result = invokeEnhancer("-help");
    63          String outputString = result.getOutputString();
    64          String errorString = result.getErrorString();
    65          assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    66          assertTrue("Expected Usage message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("javax.jdo.Enhancer"));
    67      }
    68
    69      public void testHOption() {
    70          // invoke enhancer with a usage option
    71          InvocationResult result = invokeEnhancer("-h");
    72          String outputString = result.getOutputString();
    73          String errorString = result.getErrorString();
    74          assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    75          assertTrue("Expected Usage message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("javax.jdo.Enhancer"));
    76      }
    77
    78      public void testInvalidOption() {
    79          // invoke enhancer with an invalid option
    80          InvocationResult result = invokeEnhancer("-poo");
    81          assertEquals("Wrong return value ", ENHANCER_USAGE_ERROR, result.getExitValue());
    82          String errorString = result.getErrorString();
    83          assertTrue("Expected Usage message from err:\n" + errorString, errorString.contains("javax.jdo.Enhancer"));
    84      }
    85
    86      public void testProperties() {
    87          // invoke enhancer with verbose option
    88          InvocationResult result = invokeEnhancer("-v");
    89          String outputString = result.getOutputString();
    90          String errorString = result.getErrorString();
    91          assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    92          assertTrue("Expected MockEnhancer vendor message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains(PROPERTY_ENHANCER_VENDOR_NAME));
    93          assertTrue("Expected MockEnhancer version message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains(PROPERTY_ENHANCER_VERSION_NUMBER));
    94          assertTrue("Expected MockEnhancer vendor message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("Mock Enhancer"));
    95          assertTrue("Expected MockEnhancer vendor message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("2.3.0"));
    96          assertTrue("Expected MockEnhancer properties message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("MockKey"));
    97      }
    98
    99      public void testVOption() {
    100         // invoke enhancer with verbose option
    101         InvocationResult result = invokeEnhancer("-v");
    102         String outputString = result.getOutputString();
    103         String errorString = result.getErrorString();
    104         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    105         assertTrue("Expected Enhancer class message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("javax.jdo.MockEnhancer"));
    106     }
    107
    108     public void testVerboseOption() {
    109         // invoke enhancer with verbose option
    110         InvocationResult result = invokeEnhancer("-verbose");
    111         String outputString = result.getOutputString();
    112         String errorString = result.getErrorString();
    113         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    114         assertTrue("Expected Enhancer class message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("javax.jdo.MockEnhancer"));
    115     }
    116
    117     public void testVerboseClasses() {
    118         // invoke enhancer with .class parameter
    119         InvocationResult result = invokeEnhancer("-v some.class");
    120         String outputString = result.getOutputString();
    121         String errorString = result.getErrorString();
    122         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    123         assertTrue("Expected class message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.class"));
    124         assertTrue("Expected number of classes from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("1"));
    125     }
    126
    127     public void testVerboseJars() {
    128         // invoke enhancer with a .jar parameter
    129         InvocationResult result = invokeEnhancer("-v some.jar");
    130         String outputString = result.getOutputString();
    131         String errorString = result.getErrorString();
    132         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    133         assertTrue("Expected jar message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jar"));
    134         assertTrue("Expected number of jars from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("1"));
    135     }
    136
    137     public void testVerboseJDOs() {
    138         // invoke enhancer with a .jdo parameter
    139         InvocationResult result = invokeEnhancer("-v some.jdo");
    140         String outputString = result.getOutputString();
    141         String errorString = result.getErrorString();
    142         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    143         assertTrue("Expected jdo message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jdo"));
    144         assertTrue("Expected number of jdos from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("1"));
    145     }
    146
    147     public void testVerboseAll() {
    148         // invoke enhancer with multiple parameters
    149         InvocationResult result = invokeEnhancer("-v some.class some.jar some.jdo");
    150         String outputString = result.getOutputString();
    151         String errorString = result.getErrorString();
    152         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    153         assertTrue("Expected jdo message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jdo"));
    154         assertTrue("Expected jar message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jar"));
    155         assertTrue("Expected class message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.class"));
    156         assertTrue("Expected number of elements from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("3"));
    157     }
    158
    159     public void testVerboseCheckonlyAll() {
    160         // invoke enhancer with a checkonly option
    161         InvocationResult result = invokeEnhancer("-v -checkonly some.class some.jar some.jdo");
    162         String outputString = result.getOutputString();
    163         String errorString = result.getErrorString();
    164         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    165         assertTrue("Expected jdo message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jdo"));
    166         assertTrue("Expected jar message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.jar"));
    167         assertTrue("Expected class message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some.class"));
    168         assertTrue("Expected number of elements from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("3"));
    169     }
    170
    171     public void testMissingPU() {
    172         // invoke enhancer with missing parameter
    173         InvocationResult result = invokeEnhancer("-v -pu");
    174         assertEquals("Wrong return value ", 3, result.getExitValue());
    175     }
    176
    177     public void testVerbosePU() {
    178         // invoke enhancer with a pu parameter
    179         InvocationResult result = invokeEnhancer("-v -pu myPU -pu yourPU");
    180         String outputString = result.getOutputString();
    181         String errorString = result.getErrorString();
    182         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    183         assertTrue("Expected pu message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("myPU"));
    184         assertTrue("Expected pu message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("yourPU"));
    185         assertTrue("Expected number of elements from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("2"));
    186     }
    187
    188     public void testClasspath() {
    189         // invoke enhancer with a classpath parameter
    190         // JDOHelper must be loadable from this path
    191         // the File.toURI should append "/" to the path, so only "target/classes" is needed
    192         InvocationResult result = invokeEnhancer("-v -cp " + basedir + "/target/classes");
    193         String outputString = result.getOutputString();
    194         String errorString = result.getErrorString();
    195         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    196         assertTrue("Expected classpath message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("target/classes"));
    197     }
    198
    199     public void testBadClasspath() {
    200         // invoke enhancer with a bad classpath parameter
    201         // JDOHelper is not loadable from this path
    202         InvocationResult result = invokeEnhancer("-v -cp target");
    203         String outputString = result.getOutputString();
    204         String errorString = result.getErrorString();
    205         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 1, result.getExitValue());
    206         assertTrue("Expected classpath error message from out:\n" + outputString + " with err:\n" + errorString, errorString.contains("JDOHelper"));
    207     }
    208
    209     public void testClasspathJar() throws IOException, InterruptedException {
    210         // invoke enhancer with a classpath parameter
    211         // JDOHelper must be loadable from this path
    212         // create the jar file from the target/classes directory
    213         String uuid = UUID.randomUUID().toString();
    214         File uuidDir = new File(basedir + "/target/" + uuid);
    215         uuidDir.mkdirs();
    216         String enhancerJar = "target/" + uuid + "/enhancer-test.jar";
    217         String enhancerJarPathname = basedir + "/" + enhancerJar;
    218         Process create = Runtime.getRuntime().exec("jar -cf " + enhancerJarPathname + " -C " + basedir + "/target/classes .");
    219         int returnCode = create.waitFor();
    220         assertEquals("jar command returned wrong return code.", 0, returnCode);
    221         // find the jdo.jar in target
    222         InvocationResult result = invokeEnhancer("-v -cp " + enhancerJarPathname);
    223         String outputString = result.getOutputString();
    224         String errorString = result.getErrorString();
    225         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    226         assertTrue("Expected classpath message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains(enhancerJar));
    227     }
    228
    229     public void testOutputDirectory() {
    230         // invoke enhancer with an output directory parameter
    231         InvocationResult result = invokeEnhancer("-v -d some/output/directory");
    232         String outputString = result.getOutputString();
    233         String errorString = result.getErrorString();
    234         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    235         assertTrue("Expected directory message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("some/output/directory"));
    236     }
    237
    238     public void testMissingOutputDirectory() {
    239         // invoke enhancer with missing parameter
    240         InvocationResult result = invokeEnhancer("-v -d");
    241         assertEquals("Wrong return value ", 3, result.getExitValue());
    242     }
    243
    244     public void testDir() {
    245         // invoke enhancer with directory and not recurse
    246         InvocationResult result = invokeEnhancer("-v " + basedir + "/target/test-classes/enhancer-test-dir");
    247         String outputString = result.getOutputString();
    248         String errorString = result.getErrorString();
    249         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    250         assertTrue("Expected directory enhancer-test-dir in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("enhancer-test-dir"));
    251         assertTrue("Expected file file1.jdo in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file1.jdo"));
    252         assertTrue("Expected file file2.class in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file2.class"));
    253         assertTrue("Expected file file3.jar in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file3.jar"));
    254         assertFalse("Expected no directory enhancer-test-subdir in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("enhancer-test-subdir"));
    255         assertTrue("Expected 3 files to be enhanced in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("3"));
    256     }
    257
    258     public void testDirRecurse() {
    259         // invoke enhancer with directory and recurse
    260         InvocationResult result = invokeEnhancer("-v -r " + basedir + "/target/test-classes/enhancer-test-dir");
    261         String outputString = result.getOutputString();
    262         String errorString = result.getErrorString();
    263         assertEquals("Wrong exit code from Enhancer with stderr:\n" + errorString, 0, result.getExitValue());
    264         assertTrue("Expected directory enhancer-test-dir in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("enhancer-test-dir"));
    265         assertTrue("Expected directory enhancer-test-subdir in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("enhancer-test-subdir"));
    266         assertTrue("Expected file file1.jdo in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file1.jdo"));
    267         assertTrue("Expected file file2.class in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file2.class"));
    268         assertTrue("Expected file file3.jar in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file3.jar"));
    269         assertTrue("Expected file file4.jdo in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file4.jdo"));
    270         assertTrue("Expected file file5.class in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file5.class"));
    271         assertTrue("Expected file file6.jar in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("file6.jar"));
    272         assertTrue("Expected 6 files to be enhanced in message from out:\n" + outputString + " with err:\n" + errorString, outputString.contains("6"));
    273     }
    274
    275     private InvocationResult invokeEnhancer(String string) {
    276         InvocationResult result = new InvocationResult();
    277         try {
    278             // create the java command to invoke the Enhancer
    279             List<String> commands = new ArrayList<String>();
    280             // find the java command in the user's path
    281             commands.add("java");
    282             commands.add("-cp");
    283             commands.add("" + basedir + "/target/classes" + pathDelimiter + "" + basedir + "/target/test-classes");
    284             commands.add("javax.jdo.Enhancer");
    285             // add the test options (from the method parameter) to the java command
    286             String[] optionArray = string.split(" ");
    287             for (String option: optionArray) {
    288                 commands.add(option);
    289             }
    290             String[] cmdarray = commands.toArray(new String[commands.size()]);
    291             ProcessBuilder builder = new ProcessBuilder(cmdarray);
    292             Process proc = builder.start();
    293             InputStream stdout = proc.getInputStream();
    294             InputStream stderr = proc.getErrorStream();
    295             CharBuffer outBuffer = CharBuffer.allocate(1000000);
    296             CharBuffer errBuffer = CharBuffer.allocate(1000000);
    297             Thread outputThread = createReaderThread(stdout, outBuffer);
    298             Thread errorThread = createReaderThread(stderr, errBuffer);
    299             int exitValue = proc.waitFor();
    300             result.setExitValue(exitValue);
    301             errorThread.join(10000); // wait ten seconds to get stderr after process terminates
    302             outputThread.join(10000); // wait ten seconds to get stdout after process terminates
    303             result.setErrorString(errBuffer.toString());
    304             result.setOutputString(outBuffer.toString());
    305             // wait until the Enhancer command finishes
    306         } catch (InterruptedException ex) {
    307             throw new RuntimeException("InterruptedException", ex);
    308         } catch (IOException ex) {
    309             throw new RuntimeException("IOException", ex);
    310         } catch (JDOException jdoex) {
    311             jdoex.printStackTrace();
    312             Throwable[] throwables = jdoex.getNestedExceptions();
    313             System.out.println("Exception throwables of size: " + throwables.length);
    314             for (Throwable throwable: throwables) {
    315                 throwable.printStackTrace();
    316             }
    317         }
    318         return result;
    319     }
    320
    321     private Thread createReaderThread(final InputStream input, final CharBuffer output) {
    322         final Reader reader = new InputStreamReader(input);
    323         Thread thread = new Thread(
    324                 new Runnable() {
    325                     public void run() {
    326                         int count = 0;
    327                         int outputBytesRead = 0;
    328                         try {
    329                             while (-1 != (outputBytesRead = reader.read(output))) {
    330                                 count += outputBytesRead;
    331                             }
    332                         } catch (IOException e) {
    333                             e.printStackTrace();
    334                         } finally {
    335                             output.flip();
    336                         }
    337                     }
    338                 });
    339         thread.start();
    340         return thread;
    341     }
    342
    343     class InvocationResult {
    344         private int exitValue;
    345         private String errorString;
    346         private String outputString;
    347
    348         int getExitValue() {
    349             return exitValue;
    350         }
    351
    352         private void setExitValue(int exitValue) {
    353             this.exitValue = exitValue;
    354         }
    355
    356         private void setErrorString(String errorString) {
    357             this.errorString = errorString;
    358         }
    359
    360         String getErrorString() {
    361             return errorString;
    362         }
    363
    364         private void setOutputString(String outputString) {
    365             this.outputString = outputString;
    366         }
    367
    368         String getOutputString() {
    369             return outputString;
    370         }
    371
    372     }
    373
    374 }