OutputAnalyzer.java revision 2224:2a8815d86b93
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 contents of output buffer does not contain the string
187   *
188   * @param expectedString String that the buffer should not contain
189   * @throws RuntimeException If the string was found
190   */
191  public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
192    if (stdout.contains(notExpectedString)) {
193        reportDiagnosticSummary();
194        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
195    }
196    return this;
197  }
198
199  /**
200   * Verify that the stderr contents of output buffer does not contain the string
201   *
202   * @param expectedString String that the buffer should not contain
203   * @throws RuntimeException If the string was found
204   */
205  public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
206    if (stderr.contains(notExpectedString)) {
207        reportDiagnosticSummary();
208        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
209    }
210    return this;
211  }
212
213  /**
214   * Verify that the stdout and stderr contents of output buffer matches
215   * the pattern
216   *
217   * @param pattern
218   * @throws RuntimeException If the pattern was not found
219   */
220  public OutputAnalyzer shouldMatch(String pattern) {
221      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
222      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
223      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
224          reportDiagnosticSummary();
225          throw new RuntimeException("'" + pattern
226                + "' missing from stdout/stderr \n");
227      }
228      return this;
229  }
230
231  /**
232   * Verify that the stdout contents of output buffer matches the
233   * pattern
234   *
235   * @param pattern
236   * @throws RuntimeException If the pattern was not found
237   */
238  public OutputAnalyzer stdoutShouldMatch(String pattern) {
239      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
240      if (!matcher.find()) {
241          reportDiagnosticSummary();
242          throw new RuntimeException("'" + pattern
243                + "' missing from stdout \n");
244      }
245      return this;
246  }
247
248  /**
249   * Verify that the stderr 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 stderrShouldMatch(String pattern) {
256      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
257      if (!matcher.find()) {
258          reportDiagnosticSummary();
259          throw new RuntimeException("'" + pattern
260                + "' missing from stderr \n");
261      }
262      return this;
263  }
264
265  /**
266   * Verify that the stdout and stderr contents of output buffer does not
267   * match the pattern
268   *
269   * @param pattern
270   * @throws RuntimeException If the pattern was found
271   */
272  public OutputAnalyzer shouldNotMatch(String pattern) {
273      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
274      if (matcher.find()) {
275          reportDiagnosticSummary();
276          throw new RuntimeException("'" + pattern
277                  + "' found in stdout: '" + matcher.group() + "' \n");
278      }
279      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
280      if (matcher.find()) {
281          reportDiagnosticSummary();
282          throw new RuntimeException("'" + pattern
283                  + "' found in stderr: '" + matcher.group() + "' \n");
284      }
285      return this;
286  }
287
288  /**
289   * Verify that the stdout contents of output buffer does not match the
290   * pattern
291   *
292   * @param pattern
293   * @throws RuntimeException If the pattern was found
294   */
295  public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
296      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
297      if (matcher.find()) {
298          reportDiagnosticSummary();
299          throw new RuntimeException("'" + pattern
300                  + "' found in stdout \n");
301      }
302      return this;
303  }
304
305  /**
306   * Verify that the stderr 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 stderrShouldNotMatch(String pattern) {
313      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
314      if (matcher.find()) {
315          reportDiagnosticSummary();
316          throw new RuntimeException("'" + pattern
317                  + "' found in stderr \n");
318      }
319      return this;
320  }
321
322  /**
323   * Get the captured group of the first string matching the pattern.
324   * stderr is searched before stdout.
325   *
326   * @param pattern The multi-line pattern to match
327   * @param group The group to capture
328   * @return The matched string or null if no match was found
329   */
330  public String firstMatch(String pattern, int group) {
331    Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
332    Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
333    if (stderrMatcher.find()) {
334      return stderrMatcher.group(group);
335    }
336    if (stdoutMatcher.find()) {
337      return stdoutMatcher.group(group);
338    }
339    return null;
340  }
341
342  /**
343   * Get the first string matching the pattern.
344   * stderr is searched before stdout.
345   *
346   * @param pattern The multi-line pattern to match
347   * @return The matched string or null if no match was found
348   */
349  public String firstMatch(String pattern) {
350    return firstMatch(pattern, 0);
351  }
352
353  /**
354   * Verify the exit value of the process
355   *
356   * @param expectedExitValue Expected exit value from process
357   * @throws RuntimeException If the exit value from the process did not match the expected value
358   */
359  public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
360      if (getExitValue() != expectedExitValue) {
361          reportDiagnosticSummary();
362          throw new RuntimeException("Expected to get exit value of ["
363                  + expectedExitValue + "]\n");
364      }
365      return this;
366  }
367
368
369  /**
370   * Report summary that will help to diagnose the problem
371   * Currently includes:
372   *  - standard input produced by the process under test
373   *  - standard output
374   *  - exit code
375   *  Note: the command line is printed by the ProcessTools
376   */
377  public void reportDiagnosticSummary() {
378      String msg =
379          " stdout: [" + stdout + "];\n" +
380          " stderr: [" + stderr + "]\n" +
381          " exitValue = " + getExitValue() + "\n";
382
383      System.err.println(msg);
384  }
385
386
387  /**
388   * Get the contents of the output buffer (stdout and stderr)
389   *
390   * @return Content of the output buffer
391   */
392  public String getOutput() {
393    return stdout + stderr;
394  }
395
396  /**
397   * Get the contents of the stdout buffer
398   *
399   * @return Content of the stdout buffer
400   */
401  public String getStdout() {
402    return stdout;
403  }
404
405  /**
406   * Get the contents of the stderr buffer
407   *
408   * @return Content of the stderr buffer
409   */
410  public String getStderr() {
411    return stderr;
412  }
413
414  /**
415   * Get the process exit value
416   *
417   * @return Process exit value
418   */
419  public int getExitValue() {
420    return exitValue;
421  }
422
423  /**
424   * Get the contents of the output buffer (stdout and stderr) as list of strings.
425   * Output will be split by newlines.
426   *
427   * @return Contents of the output buffer as list of strings
428   */
429  public List<String> asLines() {
430    return asLines(getOutput());
431  }
432
433  private List<String> asLines(String buffer) {
434    return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
435  }
436}
437