< prev index next >

test/lib/jdk/test/lib/process/OutputAnalyzer.java

Print this page
rev 51638 : [mq]: 8210112
rev 51639 : [mq]: 8210112-1
rev 51640 : [mq]: 8210112-2

@@ -21,132 +21,133 @@
  * questions.
  */
 
 package jdk.test.lib.process;
 
+import jdk.test.lib.Asserts;
+
 import java.io.IOException;
 import java.io.PrintStream;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public final class OutputAnalyzer {
 
-    private final String stdout;
-    private final String stderr;
-    private final int exitValue;
-
+    private final OutputBuffer buffer;
     /**
      * Create an OutputAnalyzer, a utility class for verifying output and exit
      * value from a Process
      *
      * @param process Process to analyze
      * @throws IOException If an I/O error occurs.
      */
     public OutputAnalyzer(Process process) throws IOException {
-        OutputBuffer output = ProcessTools.getOutput(process);
-        exitValue = process.exitValue();
-        this.stdout = output.getStdout();
-        this.stderr = output.getStderr();
+        buffer = OutputBuffer.of(process);
     }
 
     /**
      * Create an OutputAnalyzer, a utility class for verifying output
      *
      * @param buf String buffer to analyze
      */
     public OutputAnalyzer(String buf) {
-        this(buf, buf);
+        buffer = OutputBuffer.of(buf, buf);
     }
 
     /**
      * Create an OutputAnalyzer, a utility class for verifying output
      *
      * @param stdout stdout buffer to analyze
      * @param stderr stderr buffer to analyze
      */
     public OutputAnalyzer(String stdout, String stderr) {
-        this.stdout = stdout;
-        this.stderr = stderr;
-        exitValue = -1;
+        buffer = OutputBuffer.of(stdout, stderr);
     }
 
     /**
      * Verify that the stdout contents of output buffer is empty
      *
      * @throws RuntimeException
      *             If stdout was not empty
      */
-    public void stdoutShouldBeEmpty() {
+    public OutputAnalyzer stdoutShouldBeEmpty() {
         if (!getStdout().isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stdout was not empty");
         }
+        return this;
     }
 
     /**
      * Verify that the stderr contents of output buffer is empty
      *
      * @throws RuntimeException
      *             If stderr was not empty
      */
-    public void stderrShouldBeEmpty() {
+    public OutputAnalyzer stderrShouldBeEmpty() {
         if (!getStderr().isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stderr was not empty");
         }
+        return this;
     }
 
     /**
      * Verify that the stderr contents of output buffer is empty,
      * after filtering out the Hotspot warning messages
      *
      * @throws RuntimeException
      *             If stderr was not empty
      */
-    public void stderrShouldBeEmptyIgnoreVMWarnings() {
+    public OutputAnalyzer stderrShouldBeEmptyIgnoreVMWarnings() {
         if (!getStderr().replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stderr was not empty");
         }
+        return this;
     }
 
     /**
      * Verify that the stdout contents of output buffer is not empty
      *
      * @throws RuntimeException
      *             If stdout was empty
      */
-    public void stdoutShouldNotBeEmpty() {
+    public OutputAnalyzer stdoutShouldNotBeEmpty() {
         if (getStdout().isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stdout was empty");
         }
+        return this;
     }
 
     /**
      * Verify that the stderr contents of output buffer is not empty
      *
      * @throws RuntimeException
      *             If stderr was empty
      */
-    public void stderrShouldNotBeEmpty() {
+    public OutputAnalyzer stderrShouldNotBeEmpty() {
         if (getStderr().isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stderr was empty");
         }
+        return this;
     }
 
     /**
      * Verify that the stdout and stderr contents of output buffer contains the string
      *
      * @param expectedString String that buffer should contain
      * @throws RuntimeException If the string was not found
      */
     public OutputAnalyzer shouldContain(String expectedString) {
+        String stdout = getStdout();
+        String stderr = getStderr();
         if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
         }
         return this;

@@ -157,10 +158,11 @@
      *
      * @param expectedString String that buffer should contain
      * @throws RuntimeException If the string was not found
      */
     public OutputAnalyzer stdoutShouldContain(String expectedString) {
+        String stdout = getStdout();
         if (!stdout.contains(expectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
         }
         return this;

@@ -171,24 +173,27 @@
      *
      * @param expectedString String that buffer should contain
      * @throws RuntimeException If the string was not found
      */
     public OutputAnalyzer stderrShouldContain(String expectedString) {
+        String stderr = getStderr();
         if (!stderr.contains(expectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
         }
         return this;
     }
 
     /**
      * Verify that the stdout and stderr contents of output buffer does not contain the string
      *
-     * @param expectedString String that the buffer should not contain
+     * @param notExpectedString String that the buffer should not contain
      * @throws RuntimeException If the string was found
      */
     public OutputAnalyzer shouldNotContain(String notExpectedString) {
+        String stdout = getStdout();
+        String stderr = getStderr();
         if (stdout.contains(notExpectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
         }
         if (stderr.contains(notExpectedString)) {

@@ -202,10 +207,12 @@
      * Verify that the stdout and stderr contents of output buffer are empty
      *
      * @throws RuntimeException If the stdout and stderr are not empty
      */
     public OutputAnalyzer shouldBeEmpty() {
+        String stdout = getStdout();
+        String stderr = getStderr();
         if (!stdout.isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stdout was not empty");
         }
         if (!stderr.isEmpty()) {

@@ -216,28 +223,30 @@
     }
 
     /**
      * Verify that the stdout contents of output buffer does not contain the string
      *
-     * @param expectedString String that the buffer should not contain
+     * @param notExpectedString String that the buffer should not contain
      * @throws RuntimeException If the string was found
      */
     public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
+        String stdout = getStdout();
         if (stdout.contains(notExpectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
         }
         return this;
     }
 
     /**
      * Verify that the stderr contents of output buffer does not contain the string
      *
-     * @param expectedString String that the buffer should not contain
+     * @param notExpectedString String that the buffer should not contain
      * @throws RuntimeException If the string was found
      */
     public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
+        String stderr = getStderr();
         if (stderr.contains(notExpectedString)) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
         }
         return this;

@@ -245,36 +254,40 @@
 
     /**
      * Verify that the stdout and stderr contents of output buffer matches
      * the pattern
      *
-     * @param pattern
+     * @param regexp
      * @throws RuntimeException If the pattern was not found
      */
-    public OutputAnalyzer shouldMatch(String pattern) {
-        Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-        Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+    public OutputAnalyzer shouldMatch(String regexp) {
+        String stdout = getStdout();
+        String stderr = getStderr();
+        Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE);
+        Matcher stdoutMatcher = pattern.matcher(stdout);
+        Matcher stderrMatcher = pattern.matcher(stderr);
         if (!stdoutMatcher.find() && !stderrMatcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                   + "' missing from stdout/stderr \n");
         }
         return this;
     }
 
     /**
      * Verify that the stdout contents of output buffer matches the
      * pattern
      *
-     * @param pattern
+     * @param regexp
      * @throws RuntimeException If the pattern was not found
      */
-    public OutputAnalyzer stdoutShouldMatch(String pattern) {
-        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+    public OutputAnalyzer stdoutShouldMatch(String regexp) {
+        String stdout = getStdout();
+        Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stdout);
         if (!matcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                   + "' missing from stdout \n");
         }
         return this;
     }
 

@@ -284,11 +297,11 @@
      *
      * @param pattern
      * @throws RuntimeException If the pattern was not found
      */
     public OutputAnalyzer stderrShouldMatch(String pattern) {
-
+        String stderr = getStderr();
         Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
         if (!matcher.find()) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + pattern
                   + "' missing from stderr \n");

@@ -298,77 +311,87 @@
 
     /**
      * Verify that the stdout and stderr contents of output buffer does not
      * match the pattern
      *
-     * @param pattern
+     * @param regexp
      * @throws RuntimeException If the pattern was found
      */
-    public OutputAnalyzer shouldNotMatch(String pattern) {
-        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+    public OutputAnalyzer shouldNotMatch(String regexp) {
+        String stdout = getStdout();
+        Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE);
+        Matcher matcher = pattern.matcher(stdout);
         if (matcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                     + "' found in stdout: '" + matcher.group() + "' \n");
         }
-        matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+
+        String stderr = getStderr();
+        matcher = pattern.matcher(stderr);
         if (matcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                     + "' found in stderr: '" + matcher.group() + "' \n");
         }
+
         return this;
     }
 
     /**
      * Verify that the stdout contents of output buffer does not match the
      * pattern
      *
-     * @param pattern
+     * @param regexp
      * @throws RuntimeException If the pattern was found
      */
-    public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
-        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+    public OutputAnalyzer stdoutShouldNotMatch(String regexp) {
+        String stdout = getStdout();
+        Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stdout);
         if (matcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                     + "' found in stdout \n");
         }
         return this;
     }
 
     /**
      * Verify that the stderr contents of output buffer does not match the
      * pattern
      *
-     * @param pattern
+     * @param regexp
      * @throws RuntimeException If the pattern was found
      */
-    public OutputAnalyzer stderrShouldNotMatch(String pattern) {
-        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+    public OutputAnalyzer stderrShouldNotMatch(String regexp) {
+        String stderr = getStderr();
+        Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stderr);
         if (matcher.find()) {
             reportDiagnosticSummary();
-            throw new RuntimeException("'" + pattern
+            throw new RuntimeException("'" + regexp
                     + "' found in stderr \n");
         }
         return this;
     }
 
     /**
      * Get the captured group of the first string matching the pattern.
      * stderr is searched before stdout.
      *
-     * @param pattern The multi-line pattern to match
+     * @param regexp The multi-line pattern to match
      * @param group The group to capture
      * @return The matched string or null if no match was found
      */
-    public String firstMatch(String pattern, int group) {
-        Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-        Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+    public String firstMatch(String regexp, int group) {
+        Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE);
+        String stderr = getStderr();
+        Matcher stderrMatcher = pattern.matcher(stderr);
         if (stderrMatcher.find()) {
             return stderrMatcher.group(group);
         }
+        String stdout = getStdout();
+        Matcher stdoutMatcher = pattern.matcher(stdout);
         if (stdoutMatcher.find()) {
             return stdoutMatcher.group(group);
         }
         return null;
     }

@@ -423,12 +446,12 @@
      *  - exit code
      *  Note: the command line is printed by the ProcessTools
      */
     public void reportDiagnosticSummary() {
         String msg =
-            " stdout: [" + stdout + "];\n" +
-            " stderr: [" + stderr + "]\n" +
+            " stdout: [" + getStdout() + "];\n" +
+            " stderr: [" + getStderr() + "]\n" +
             " exitValue = " + getExitValue() + "\n";
 
         System.err.println(msg);
     }
 

@@ -456,38 +479,38 @@
      * Get the contents of the output buffer (stdout and stderr)
      *
      * @return Content of the output buffer
      */
     public String getOutput() {
-        return stdout + stderr;
+        return getStdout() + getStderr();
     }
 
     /**
      * Get the contents of the stdout buffer
      *
      * @return Content of the stdout buffer
      */
     public String getStdout() {
-        return stdout;
+        return buffer.getStdout();
     }
 
     /**
      * Get the contents of the stderr buffer
      *
      * @return Content of the stderr buffer
      */
     public String getStderr() {
-        return stderr;
+        return buffer.getStderr();
     }
 
     /**
      * Get the process exit value
      *
      * @return Process exit value
      */
     public int getExitValue() {
-        return exitValue;
+        return buffer.getExitValue();
     }
 
     /**
      * Get the contents of the output buffer (stdout and stderr) as list of strings.
      * Output will be split by newlines.

@@ -497,11 +520,11 @@
     public List<String> asLines() {
         return asLines(getOutput());
     }
 
     private List<String> asLines(String buffer) {
-        return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
+        return Arrays.asList(buffer.split("\\R"));
     }
 
 
     private static final String jvmwarningmsg = ".* VM warning:.*";
 

@@ -510,10 +533,12 @@
      * filtering out the HotSpot warning messages.
      *
      * @throws RuntimeException If the stdout and stderr are not empty
      */
     public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() {
+        String stdout = getStdout();
+        String stderr = getStderr();
         if (!stdout.isEmpty()) {
             reportDiagnosticSummary();
             throw new RuntimeException("stdout was not empty");
         }
         if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {

@@ -529,11 +554,11 @@
      *
      * @param pattern
      * @throws RuntimeException If the pattern was not found
      */
     public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) {
-        String stderr = this.stderr.replaceAll(jvmwarningmsg + "\\R", "");
+        String stderr = getStderr().replaceAll(jvmwarningmsg + "\\R", "");
         Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
         if (!matcher.find()) {
             reportDiagnosticSummary();
             throw new RuntimeException("'" + pattern
                   + "' missing from stderr \n");

@@ -546,12 +571,120 @@
      * JVM warning msgs, as list of strings. Output is split by newlines.
      *
      * @return Contents of the output buffer as list of strings
      */
     public List<String> asLinesWithoutVMWarnings() {
-        return Arrays.asList(getOutput().split("\\R"))
-                .stream()
+        return Arrays.stream(getOutput().split("\\R"))
                 .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate())
                 .collect(Collectors.toList());
     }
 
+    /**
+     * @see #shouldMatchByLine(String, String, String)
+     */
+    public OutputAnalyzer shouldMatchByLine(String pattern) {
+        return shouldMatchByLine(null, null, pattern);
+    }
+
+    /**
+     * @see #stdoutShouldMatchByLine(String, String, String)
+     */
+    public OutputAnalyzer stdoutShouldMatchByLine(String pattern) {
+        return stdoutShouldMatchByLine(null, null, pattern);
+    }
+
+    /**
+     * @see #shouldMatchByLine(String, String, String)
+     */
+    public OutputAnalyzer shouldMatchByLineFrom(String from, String pattern) {
+        return shouldMatchByLine(from, null, pattern);
+    }
+
+    /**
+     * @see #shouldMatchByLine(String, String, String)
+     */
+    public OutputAnalyzer shouldMatchByLineTo(String to, String pattern) {
+        return shouldMatchByLine(null, to, pattern);
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer match the
+     * {@code pattern} line by line. The whole output could be matched or
+     * just a subset of it.
+     *
+     * @param from
+     *            The line from where output will be matched.
+     *            Set {@code from} to null for matching from the first line.
+     * @param to
+     *            The line until where output will be matched.
+     *            Set {@code to} to null for matching until the last line.
+     * @param pattern
+     *            Matching pattern
+     */
+    public OutputAnalyzer shouldMatchByLine(String from, String to, String pattern) {
+        return shouldMatchByLine(getOutput(), from, to, pattern);
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer matches the
+     * {@code pattern} line by line. The whole stdout could be matched or
+     * just a subset of it.
+     *
+     * @param from
+     *            The line from where stdout will be matched.
+     *            Set {@code from} to null for matching from the first line.
+     * @param to
+     *            The line until where stdout will be matched.
+     *            Set {@code to} to null for matching until the last line.
+     * @param pattern
+     *            Matching pattern
+     */
+    public OutputAnalyzer stdoutShouldMatchByLine(String from, String to, String pattern) {
+        return shouldMatchByLine(getStdout(), from, to, pattern);
+    }
+
+    private OutputAnalyzer shouldMatchByLine(String buffer, String from, String to, String pattern) {
+        List<String> lines = asLines(buffer);
+
+        int fromIndex = 0;
+        if (from != null) {
+            fromIndex = indexOf(lines, from);
+            Asserts.assertGreaterThan(fromIndex, -1,
+                    "The line/pattern '" + from + "' from where the output should match can not be found");
+        }
+
+        int toIndex = lines.size();
+        if (to != null) {
+            toIndex = indexOf(lines, to);
+            Asserts.assertGreaterThan(toIndex, -1,
+                    "The line/pattern '" + to + "' until where the output should match can not be found");
+        }
+
+        List<String> subList = lines.subList(fromIndex, toIndex);
+        Asserts.assertFalse(subList.isEmpty(), "There are no lines to check");
+
+        subList.stream()
+               .filter(Pattern.compile(pattern).asPredicate().negate())
+               .findAny()
+               .ifPresent(line -> Asserts.assertTrue(false,
+                       "The line '" + line + "' does not match pattern '" + pattern + "'"));
+
+        return this;
+    }
+
+    /**
+     * Check if there is a line matching {@code regexp} and return its index
+     *
+     * @param regexp Matching pattern
+     * @return Index of first matching line
+     */
+    private int indexOf(List<String> lines, String regexp) {
+        Pattern pattern = Pattern.compile(regexp);
+        for (int i = 0; i < lines.size(); i++) {
+            if (pattern.matcher(lines.get(i)).matches()) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
 }
< prev index next >