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 24 package jdk.test.lib.process; 25 26 import java.io.IOException; 27 import java.io.PrintStream; 28 import java.util.Arrays; 29 import java.util.List; 30 import java.util.regex.Matcher; 31 import java.util.regex.Pattern; 32 33 public 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 }