OutputAnalyzer.java revision 2609:df33ef1dc163
1/*
2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package jdk.test.lib.process;
25
26import java.io.IOException;
27import java.io.PrintStream;
28import java.util.Arrays;
29import java.util.List;
30import java.util.regex.Matcher;
31import java.util.regex.Pattern;
32
33public final class OutputAnalyzer {
34
35  private final String stdout;
36  private final String stderr;
37  private final int exitValue;
38
39  /**
40   * Create an OutputAnalyzer, a utility class for verifying output and exit
41   * value from a Process
42   *
43   * @param process Process to analyze
44   * @throws IOException If an I/O error occurs.
45   */
46  public OutputAnalyzer(Process process) throws IOException {
47    OutputBuffer output = ProcessTools.getOutput(process);
48    exitValue = process.exitValue();
49    this.stdout = output.getStdout();
50    this.stderr = output.getStderr();
51  }
52
53  /**
54   * Create an OutputAnalyzer, a utility class for verifying output
55   *
56   * @param buf String buffer to analyze
57   */
58  public OutputAnalyzer(String buf) {
59    this(buf, buf);
60  }
61
62  /**
63   * Create an OutputAnalyzer, a utility class for verifying output
64   *
65   * @param stdout stdout buffer to analyze
66   * @param stderr stderr buffer to analyze
67   */
68  public OutputAnalyzer(String stdout, String stderr) {
69    this.stdout = stdout;
70    this.stderr = stderr;
71    exitValue = -1;
72  }
73
74  /**
75   * Verify that the stdout contents of output buffer is empty
76   *
77   * @throws RuntimeException
78   *             If stdout was not empty
79   */
80  public void stdoutShouldBeEmpty() {
81    if (!getStdout().isEmpty()) {
82      reportDiagnosticSummary();
83      throw new RuntimeException("stdout was not empty");
84    }
85  }
86
87  /**
88   * Verify that the stderr contents of output buffer is empty
89   *
90   * @throws RuntimeException
91   *             If stderr was not empty
92   */
93  public void stderrShouldBeEmpty() {
94    if (!getStderr().isEmpty()) {
95      reportDiagnosticSummary();
96      throw new RuntimeException("stderr was not empty");
97    }
98  }
99
100  /**
101   * Verify that the stdout contents of output buffer is not empty
102   *
103   * @throws RuntimeException
104   *             If stdout was empty
105   */
106  public void stdoutShouldNotBeEmpty() {
107    if (getStdout().isEmpty()) {
108      reportDiagnosticSummary();
109      throw new RuntimeException("stdout was empty");
110    }
111  }
112
113  /**
114   * Verify that the stderr contents of output buffer is not empty
115   *
116   * @throws RuntimeException
117   *             If stderr was empty
118   */
119  public void stderrShouldNotBeEmpty() {
120    if (getStderr().isEmpty()) {
121      reportDiagnosticSummary();
122      throw new RuntimeException("stderr was empty");
123    }
124  }
125
126    /**
127   * Verify that the stdout and stderr contents of output buffer contains the string
128   *
129   * @param expectedString String that buffer should contain
130   * @throws RuntimeException If the string was not found
131   */
132  public OutputAnalyzer shouldContain(String expectedString) {
133    if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
134        reportDiagnosticSummary();
135        throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
136    }
137    return this;
138  }
139
140  /**
141   * Verify that the stdout contents of output buffer contains the string
142   *
143   * @param expectedString String that buffer should contain
144   * @throws RuntimeException If the string was not found
145   */
146  public OutputAnalyzer stdoutShouldContain(String expectedString) {
147    if (!stdout.contains(expectedString)) {
148        reportDiagnosticSummary();
149        throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
150    }
151    return this;
152  }
153
154  /**
155   * Verify that the stderr contents of output buffer contains the string
156   *
157   * @param expectedString String that buffer should contain
158   * @throws RuntimeException If the string was not found
159   */
160  public OutputAnalyzer stderrShouldContain(String expectedString) {
161    if (!stderr.contains(expectedString)) {
162        reportDiagnosticSummary();
163        throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
164    }
165    return this;
166  }
167
168  /**
169   * Verify that the stdout and stderr contents of output buffer does not contain the string
170   *
171   * @param expectedString String that the buffer should not contain
172   * @throws RuntimeException If the string was found
173   */
174  public OutputAnalyzer shouldNotContain(String notExpectedString) {
175    if (stdout.contains(notExpectedString)) {
176        reportDiagnosticSummary();
177        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
178    }
179    if (stderr.contains(notExpectedString)) {
180        reportDiagnosticSummary();
181        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
182    }
183    return this;
184  }
185
186  /**
187   * Verify that the stdout and stderr contents of output buffer does not contain the string
188   *
189   * @throws RuntimeException If the string was found
190   */
191  public OutputAnalyzer shouldBeEmpty() {
192    if (!stdout.isEmpty()) {
193        reportDiagnosticSummary();
194        throw new RuntimeException("stdout was not empty");
195    }
196    if (!stderr.isEmpty()) {
197        reportDiagnosticSummary();
198        throw new RuntimeException("stderr was not empty");
199    }
200    return this;
201  }
202
203  /**
204   * Verify that the stdout contents of output buffer does not contain the string
205   *
206   * @param expectedString String that the buffer should not contain
207   * @throws RuntimeException If the string was found
208   */
209  public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
210    if (stdout.contains(notExpectedString)) {
211        reportDiagnosticSummary();
212        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
213    }
214    return this;
215  }
216
217  /**
218   * Verify that the stderr contents of output buffer does not contain the string
219   *
220   * @param expectedString String that the buffer should not contain
221   * @throws RuntimeException If the string was found
222   */
223  public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
224    if (stderr.contains(notExpectedString)) {
225        reportDiagnosticSummary();
226        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
227    }
228    return this;
229  }
230
231  /**
232   * Verify that the stdout and stderr contents of output buffer matches
233   * the pattern
234   *
235   * @param pattern
236   * @throws RuntimeException If the pattern was not found
237   */
238  public OutputAnalyzer shouldMatch(String pattern) {
239      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
240      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
241      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
242          reportDiagnosticSummary();
243          throw new RuntimeException("'" + pattern
244                + "' missing from stdout/stderr \n");
245      }
246      return this;
247  }
248
249  /**
250   * Verify that the stdout contents of output buffer matches the
251   * pattern
252   *
253   * @param pattern
254   * @throws RuntimeException If the pattern was not found
255   */
256  public OutputAnalyzer stdoutShouldMatch(String pattern) {
257      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
258      if (!matcher.find()) {
259          reportDiagnosticSummary();
260          throw new RuntimeException("'" + pattern
261                + "' missing from stdout \n");
262      }
263      return this;
264  }
265
266  /**
267   * Verify that the stderr contents of output buffer matches the
268   * pattern
269   *
270   * @param pattern
271   * @throws RuntimeException If the pattern was not found
272   */
273  public OutputAnalyzer stderrShouldMatch(String pattern) {
274      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
275      if (!matcher.find()) {
276          reportDiagnosticSummary();
277          throw new RuntimeException("'" + pattern
278                + "' missing from stderr \n");
279      }
280      return this;
281  }
282
283  /**
284   * Verify that the stdout and stderr contents of output buffer does not
285   * match the pattern
286   *
287   * @param pattern
288   * @throws RuntimeException If the pattern was found
289   */
290  public OutputAnalyzer shouldNotMatch(String pattern) {
291      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
292      if (matcher.find()) {
293          reportDiagnosticSummary();
294          throw new RuntimeException("'" + pattern
295                  + "' found in stdout: '" + matcher.group() + "' \n");
296      }
297      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
298      if (matcher.find()) {
299          reportDiagnosticSummary();
300          throw new RuntimeException("'" + pattern
301                  + "' found in stderr: '" + matcher.group() + "' \n");
302      }
303      return this;
304  }
305
306  /**
307   * Verify that the stdout contents of output buffer does not match the
308   * pattern
309   *
310   * @param pattern
311   * @throws RuntimeException If the pattern was found
312   */
313  public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
314      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
315      if (matcher.find()) {
316          reportDiagnosticSummary();
317          throw new RuntimeException("'" + pattern
318                  + "' found in stdout \n");
319      }
320      return this;
321  }
322
323  /**
324   * Verify that the stderr contents of output buffer does not match the
325   * pattern
326   *
327   * @param pattern
328   * @throws RuntimeException If the pattern was found
329   */
330  public OutputAnalyzer stderrShouldNotMatch(String pattern) {
331      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
332      if (matcher.find()) {
333          reportDiagnosticSummary();
334          throw new RuntimeException("'" + pattern
335                  + "' found in stderr \n");
336      }
337      return this;
338  }
339
340  /**
341   * Get the captured group of the first string matching the pattern.
342   * stderr is searched before stdout.
343   *
344   * @param pattern The multi-line pattern to match
345   * @param group The group to capture
346   * @return The matched string or null if no match was found
347   */
348  public String firstMatch(String pattern, int group) {
349    Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
350    Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
351    if (stderrMatcher.find()) {
352      return stderrMatcher.group(group);
353    }
354    if (stdoutMatcher.find()) {
355      return stdoutMatcher.group(group);
356    }
357    return null;
358  }
359
360  /**
361   * Get the first string matching the pattern.
362   * stderr is searched before stdout.
363   *
364   * @param pattern The multi-line pattern to match
365   * @return The matched string or null if no match was found
366   */
367  public String firstMatch(String pattern) {
368    return firstMatch(pattern, 0);
369  }
370
371  /**
372   * Verify the exit value of the process
373   *
374   * @param expectedExitValue Expected exit value from process
375   * @throws RuntimeException If the exit value from the process did not match the expected value
376   */
377  public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
378      if (getExitValue() != expectedExitValue) {
379          reportDiagnosticSummary();
380          throw new RuntimeException("Expected to get exit value of ["
381                  + expectedExitValue + "]\n");
382      }
383      return this;
384  }
385
386  /**
387   * Verify the exit value of the process
388   *
389   * @param notExpectedExitValue Unexpected exit value from process
390   * @throws RuntimeException If the exit value from the process did match the expected value
391   */
392  public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
393      if (getExitValue() == notExpectedExitValue) {
394          reportDiagnosticSummary();
395          throw new RuntimeException("Unexpected to get exit value of ["
396                  + notExpectedExitValue + "]\n");
397      }
398      return this;
399  }
400
401
402  /**
403   * Report summary that will help to diagnose the problem
404   * Currently includes:
405   *  - standard input produced by the process under test
406   *  - standard output
407   *  - exit code
408   *  Note: the command line is printed by the ProcessTools
409   */
410  public void reportDiagnosticSummary() {
411      String msg =
412          " stdout: [" + stdout + "];\n" +
413          " stderr: [" + stderr + "]\n" +
414          " exitValue = " + getExitValue() + "\n";
415
416      System.err.println(msg);
417  }
418
419  /**
420   * Print the stdout buffer to the given {@code PrintStream}.
421   *
422   * @return this OutputAnalyzer
423   */
424  public OutputAnalyzer outputTo(PrintStream out) {
425      out.println(getStdout());
426      return this;
427  }
428
429  /**
430   * Print the stderr buffer to the given {@code PrintStream}.
431   *
432   * @return this OutputAnalyzer
433   */
434  public OutputAnalyzer errorTo(PrintStream out) {
435      out.println(getStderr());
436      return this;
437  }
438
439  /**
440   * Get the contents of the output buffer (stdout and stderr)
441   *
442   * @return Content of the output buffer
443   */
444  public String getOutput() {
445    return stdout + stderr;
446  }
447
448  /**
449   * Get the contents of the stdout buffer
450   *
451   * @return Content of the stdout buffer
452   */
453  public String getStdout() {
454    return stdout;
455  }
456
457  /**
458   * Get the contents of the stderr buffer
459   *
460   * @return Content of the stderr buffer
461   */
462  public String getStderr() {
463    return stderr;
464  }
465
466  /**
467   * Get the process exit value
468   *
469   * @return Process exit value
470   */
471  public int getExitValue() {
472    return exitValue;
473  }
474
475  /**
476   * Get the contents of the output buffer (stdout and stderr) as list of strings.
477   * Output will be split by newlines.
478   *
479   * @return Contents of the output buffer as list of strings
480   */
481  public List<String> asLines() {
482    return asLines(getOutput());
483  }
484
485  private List<String> asLines(String buffer) {
486    return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
487  }
488}
489