OutputAnalyzer.java revision 2452:5fb86d73e54d
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.util.Arrays;
28import java.util.List;
29import java.util.regex.Matcher;
30import java.util.regex.Pattern;
31
32public final class OutputAnalyzer {
33
34  private final String stdout;
35  private final String stderr;
36  private final int exitValue;
37
38  /**
39   * Create an OutputAnalyzer, a utility class for verifying output and exit
40   * value from a Process
41   *
42   * @param process Process to analyze
43   * @throws IOException If an I/O error occurs.
44   */
45  public OutputAnalyzer(Process process) throws IOException {
46    OutputBuffer output = ProcessTools.getOutput(process);
47    exitValue = process.exitValue();
48    this.stdout = output.getStdout();
49    this.stderr = output.getStderr();
50  }
51
52  /**
53   * Create an OutputAnalyzer, a utility class for verifying output
54   *
55   * @param buf String buffer to analyze
56   */
57  public OutputAnalyzer(String buf) {
58    this(buf, buf);
59  }
60
61  /**
62   * Create an OutputAnalyzer, a utility class for verifying output
63   *
64   * @param stdout stdout buffer to analyze
65   * @param stderr stderr buffer to analyze
66   */
67  public OutputAnalyzer(String stdout, String stderr) {
68    this.stdout = stdout;
69    this.stderr = stderr;
70    exitValue = -1;
71  }
72
73  /**
74   * Verify that the stdout contents of output buffer is empty
75   *
76   * @throws RuntimeException
77   *             If stdout was not empty
78   */
79  public void stdoutShouldBeEmpty() {
80    if (!getStdout().isEmpty()) {
81      reportDiagnosticSummary();
82      throw new RuntimeException("stdout was not empty");
83    }
84  }
85
86  /**
87   * Verify that the stderr contents of output buffer is empty
88   *
89   * @throws RuntimeException
90   *             If stderr was not empty
91   */
92  public void stderrShouldBeEmpty() {
93    if (!getStderr().isEmpty()) {
94      reportDiagnosticSummary();
95      throw new RuntimeException("stderr was not empty");
96    }
97  }
98
99  /**
100   * Verify that the stdout contents of output buffer is not empty
101   *
102   * @throws RuntimeException
103   *             If stdout was empty
104   */
105  public void stdoutShouldNotBeEmpty() {
106    if (getStdout().isEmpty()) {
107      reportDiagnosticSummary();
108      throw new RuntimeException("stdout was empty");
109    }
110  }
111
112  /**
113   * Verify that the stderr contents of output buffer is not empty
114   *
115   * @throws RuntimeException
116   *             If stderr was empty
117   */
118  public void stderrShouldNotBeEmpty() {
119    if (getStderr().isEmpty()) {
120      reportDiagnosticSummary();
121      throw new RuntimeException("stderr was empty");
122    }
123  }
124
125    /**
126   * Verify that the stdout and stderr contents of output buffer contains the string
127   *
128   * @param expectedString String that buffer should contain
129   * @throws RuntimeException If the string was not found
130   */
131  public OutputAnalyzer shouldContain(String expectedString) {
132    if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
133        reportDiagnosticSummary();
134        throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
135    }
136    return this;
137  }
138
139  /**
140   * Verify that the stdout contents of output buffer contains the string
141   *
142   * @param expectedString String that buffer should contain
143   * @throws RuntimeException If the string was not found
144   */
145  public OutputAnalyzer stdoutShouldContain(String expectedString) {
146    if (!stdout.contains(expectedString)) {
147        reportDiagnosticSummary();
148        throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
149    }
150    return this;
151  }
152
153  /**
154   * Verify that the stderr contents of output buffer contains the string
155   *
156   * @param expectedString String that buffer should contain
157   * @throws RuntimeException If the string was not found
158   */
159  public OutputAnalyzer stderrShouldContain(String expectedString) {
160    if (!stderr.contains(expectedString)) {
161        reportDiagnosticSummary();
162        throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
163    }
164    return this;
165  }
166
167  /**
168   * Verify that the stdout and stderr contents of output buffer does not contain the string
169   *
170   * @param expectedString String that the buffer should not contain
171   * @throws RuntimeException If the string was found
172   */
173  public OutputAnalyzer shouldNotContain(String notExpectedString) {
174    if (stdout.contains(notExpectedString)) {
175        reportDiagnosticSummary();
176        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
177    }
178    if (stderr.contains(notExpectedString)) {
179        reportDiagnosticSummary();
180        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
181    }
182    return this;
183  }
184
185  /**
186   * Verify that the stdout and stderr contents of output buffer does not contain the string
187   *
188   * @throws RuntimeException If the string was found
189   */
190  public OutputAnalyzer shouldBeEmpty() {
191    if (!stdout.isEmpty()) {
192        reportDiagnosticSummary();
193        throw new RuntimeException("stdout was not empty");
194    }
195    if (!stderr.isEmpty()) {
196        reportDiagnosticSummary();
197        throw new RuntimeException("stderr was not empty");
198    }
199    return this;
200  }
201
202  /**
203   * Verify that the stdout contents of output buffer does not contain the string
204   *
205   * @param expectedString String that the buffer should not contain
206   * @throws RuntimeException If the string was found
207   */
208  public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
209    if (stdout.contains(notExpectedString)) {
210        reportDiagnosticSummary();
211        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
212    }
213    return this;
214  }
215
216  /**
217   * Verify that the stderr contents of output buffer does not contain the string
218   *
219   * @param expectedString String that the buffer should not contain
220   * @throws RuntimeException If the string was found
221   */
222  public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
223    if (stderr.contains(notExpectedString)) {
224        reportDiagnosticSummary();
225        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
226    }
227    return this;
228  }
229
230  /**
231   * Verify that the stdout and stderr contents of output buffer matches
232   * the pattern
233   *
234   * @param pattern
235   * @throws RuntimeException If the pattern was not found
236   */
237  public OutputAnalyzer shouldMatch(String pattern) {
238      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
239      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
240      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
241          reportDiagnosticSummary();
242          throw new RuntimeException("'" + pattern
243                + "' missing from stdout/stderr \n");
244      }
245      return this;
246  }
247
248  /**
249   * Verify that the stdout contents of output buffer matches the
250   * pattern
251   *
252   * @param pattern
253   * @throws RuntimeException If the pattern was not found
254   */
255  public OutputAnalyzer stdoutShouldMatch(String pattern) {
256      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
257      if (!matcher.find()) {
258          reportDiagnosticSummary();
259          throw new RuntimeException("'" + pattern
260                + "' missing from stdout \n");
261      }
262      return this;
263  }
264
265  /**
266   * Verify that the stderr contents of output buffer matches the
267   * pattern
268   *
269   * @param pattern
270   * @throws RuntimeException If the pattern was not found
271   */
272  public OutputAnalyzer stderrShouldMatch(String pattern) {
273      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
274      if (!matcher.find()) {
275          reportDiagnosticSummary();
276          throw new RuntimeException("'" + pattern
277                + "' missing from stderr \n");
278      }
279      return this;
280  }
281
282  /**
283   * Verify that the stdout and stderr contents of output buffer does not
284   * match the pattern
285   *
286   * @param pattern
287   * @throws RuntimeException If the pattern was found
288   */
289  public OutputAnalyzer shouldNotMatch(String pattern) {
290      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
291      if (matcher.find()) {
292          reportDiagnosticSummary();
293          throw new RuntimeException("'" + pattern
294                  + "' found in stdout: '" + matcher.group() + "' \n");
295      }
296      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
297      if (matcher.find()) {
298          reportDiagnosticSummary();
299          throw new RuntimeException("'" + pattern
300                  + "' found in stderr: '" + matcher.group() + "' \n");
301      }
302      return this;
303  }
304
305  /**
306   * Verify that the stdout contents of output buffer does not match the
307   * pattern
308   *
309   * @param pattern
310   * @throws RuntimeException If the pattern was found
311   */
312  public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
313      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
314      if (matcher.find()) {
315          reportDiagnosticSummary();
316          throw new RuntimeException("'" + pattern
317                  + "' found in stdout \n");
318      }
319      return this;
320  }
321
322  /**
323   * Verify that the stderr contents of output buffer does not match the
324   * pattern
325   *
326   * @param pattern
327   * @throws RuntimeException If the pattern was found
328   */
329  public OutputAnalyzer stderrShouldNotMatch(String pattern) {
330      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
331      if (matcher.find()) {
332          reportDiagnosticSummary();
333          throw new RuntimeException("'" + pattern
334                  + "' found in stderr \n");
335      }
336      return this;
337  }
338
339  /**
340   * Get the captured group of the first string matching the pattern.
341   * stderr is searched before stdout.
342   *
343   * @param pattern The multi-line pattern to match
344   * @param group The group to capture
345   * @return The matched string or null if no match was found
346   */
347  public String firstMatch(String pattern, int group) {
348    Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
349    Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
350    if (stderrMatcher.find()) {
351      return stderrMatcher.group(group);
352    }
353    if (stdoutMatcher.find()) {
354      return stdoutMatcher.group(group);
355    }
356    return null;
357  }
358
359  /**
360   * Get the first string matching the pattern.
361   * stderr is searched before stdout.
362   *
363   * @param pattern The multi-line pattern to match
364   * @return The matched string or null if no match was found
365   */
366  public String firstMatch(String pattern) {
367    return firstMatch(pattern, 0);
368  }
369
370  /**
371   * Verify the exit value of the process
372   *
373   * @param expectedExitValue Expected exit value from process
374   * @throws RuntimeException If the exit value from the process did not match the expected value
375   */
376  public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
377      if (getExitValue() != expectedExitValue) {
378          reportDiagnosticSummary();
379          throw new RuntimeException("Expected to get exit value of ["
380                  + expectedExitValue + "]\n");
381      }
382      return this;
383  }
384
385  /**
386   * Verify the exit value of the process
387   *
388   * @param notExpectedExitValue Unexpected exit value from process
389   * @throws RuntimeException If the exit value from the process did match the expected value
390   */
391  public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
392      if (getExitValue() == notExpectedExitValue) {
393          reportDiagnosticSummary();
394          throw new RuntimeException("Unexpected to get exit value of ["
395                  + notExpectedExitValue + "]\n");
396      }
397      return this;
398  }
399
400
401  /**
402   * Report summary that will help to diagnose the problem
403   * Currently includes:
404   *  - standard input produced by the process under test
405   *  - standard output
406   *  - exit code
407   *  Note: the command line is printed by the ProcessTools
408   */
409  public void reportDiagnosticSummary() {
410      String msg =
411          " stdout: [" + stdout + "];\n" +
412          " stderr: [" + stderr + "]\n" +
413          " exitValue = " + getExitValue() + "\n";
414
415      System.err.println(msg);
416  }
417
418
419  /**
420   * Get the contents of the output buffer (stdout and stderr)
421   *
422   * @return Content of the output buffer
423   */
424  public String getOutput() {
425    return stdout + stderr;
426  }
427
428  /**
429   * Get the contents of the stdout buffer
430   *
431   * @return Content of the stdout buffer
432   */
433  public String getStdout() {
434    return stdout;
435  }
436
437  /**
438   * Get the contents of the stderr buffer
439   *
440   * @return Content of the stderr buffer
441   */
442  public String getStderr() {
443    return stderr;
444  }
445
446  /**
447   * Get the process exit value
448   *
449   * @return Process exit value
450   */
451  public int getExitValue() {
452    return exitValue;
453  }
454
455  /**
456   * Get the contents of the output buffer (stdout and stderr) as list of strings.
457   * Output will be split by newlines.
458   *
459   * @return Contents of the output buffer as list of strings
460   */
461  public List<String> asLines() {
462    return asLines(getOutput());
463  }
464
465  private List<String> asLines(String buffer) {
466    return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
467  }
468}
469