1 /* 2 * Copyright (c) 2013, 2014, 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.testlibrary; 25 26 import static jdk.testlibrary.Asserts.*; 27 28 import java.io.IOException; 29 import java.io.PrintStream; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.regex.Matcher; 33 import java.util.regex.Pattern; 34 35 /** 36 * Utility class for verifying output and exit value from a {@code Process}. 37 * 38 * @deprecated This class is deprecated. Use the one from 39 * {@code <root>/test/lib/jdk/test/lib/process} 40 * 41 */ 42 @Deprecated 43 public final class OutputAnalyzer { 44 private final OutputBuffer output; 45 private final String stdout; 46 private final String stderr; 47 private final int exitValue; // useless now. output contains exit value. 48 49 /** 50 * Create an OutputAnalyzer, a utility class for verifying output and exit 51 * value from a Process. 52 * <p> 53 * OutputAnalyzer should never be instantiated directly - 54 * use {@linkplain ProcessTools#executeProcess(ProcessBuilder)} instead 55 * 56 * @param process 57 * Process to analyze 58 * @throws IOException 59 * If an I/O error occurs. 60 */ 61 OutputAnalyzer(Process process) throws IOException { 62 output = new OutputBuffer(process); 63 exitValue = -1; 64 this.stdout = null; 65 this.stderr = null; 66 } 67 68 /** 69 * Create an OutputAnalyzer, a utility class for verifying output. 70 * 71 * @param buf 72 * String buffer to analyze 73 */ 74 OutputAnalyzer(String buf) { 75 this(buf, buf); 76 } 77 78 /** 79 * Create an OutputAnalyzer, a utility class for verifying output 80 * 81 * @param stdout 82 * stdout buffer to analyze 83 * @param stderr 84 * stderr buffer to analyze 85 */ 86 OutputAnalyzer(String stdout, String stderr) { 87 this.output = null; 88 this.stdout = stdout; 89 this.stderr = stderr; 90 exitValue = -1; 91 } 92 93 /** 94 * Verify that the stdout and stderr contents of output buffer contains the 95 * string 96 * 97 * @param expectedString 98 * String that buffer should contain 99 * @throws RuntimeException 100 * If the string was not found 101 */ 102 public OutputAnalyzer shouldContain(String expectedString) { 103 if (!getStdout().contains(expectedString) 104 && !getStderr().contains(expectedString)) { 105 reportDiagnosticSummary(); 106 throw new RuntimeException("'" + expectedString 107 + "' missing from stdout/stderr \n"); 108 } 109 return this; 110 } 111 112 /** 113 * Verify that the stdout contents of output buffer contains the string 114 * 115 * @param expectedString 116 * String that buffer should contain 117 * @throws RuntimeException 118 * If the string was not found 119 */ 120 public OutputAnalyzer stdoutShouldContain(String expectedString) { 121 if (!getStdout().contains(expectedString)) { 122 reportDiagnosticSummary(); 123 throw new RuntimeException("'" + expectedString 124 + "' missing from stdout \n"); 125 } 126 return this; 127 } 128 129 /** 130 * Verify that the stderr contents of output buffer contains the string 131 * 132 * @param expectedString 133 * String that buffer should contain 134 * @throws RuntimeException 135 * If the string was not found 136 */ 137 public OutputAnalyzer stderrShouldContain(String expectedString) { 138 if (!getStderr().contains(expectedString)) { 139 reportDiagnosticSummary(); 140 throw new RuntimeException("'" + expectedString 141 + "' missing from stderr \n"); 142 } 143 return this; 144 } 145 146 /** 147 * Verify that the stdout and stderr contents of output buffer does not 148 * contain the string 149 * 150 * @param notExpectedString 151 * String that the buffer should not contain 152 * @throws RuntimeException 153 * If the string was found 154 */ 155 public OutputAnalyzer shouldNotContain(String notExpectedString) { 156 if (getStdout().contains(notExpectedString)) { 157 reportDiagnosticSummary(); 158 throw new RuntimeException("'" + notExpectedString 159 + "' found in stdout \n"); 160 } 161 if (getStderr().contains(notExpectedString)) { 162 reportDiagnosticSummary(); 163 throw new RuntimeException("'" + notExpectedString 164 + "' found in stderr \n"); 165 } 166 return this; 167 } 168 169 /** 170 * Verify that the stdout contents of output buffer does not contain the 171 * string 172 * 173 * @param notExpectedString 174 * String that the buffer should not contain 175 * @throws RuntimeException 176 * If the string was found 177 */ 178 public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { 179 if (getStdout().contains(notExpectedString)) { 180 reportDiagnosticSummary(); 181 throw new RuntimeException("'" + notExpectedString 182 + "' found in stdout \n"); 183 } 184 return this; 185 } 186 187 /** 188 * Verify that the stderr contents of output buffer does not contain the 189 * string 190 * 191 * @param notExpectedString 192 * String that the buffer should not contain 193 * @throws RuntimeException 194 * If the string was found 195 */ 196 public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { 197 if (getStderr().contains(notExpectedString)) { 198 reportDiagnosticSummary(); 199 throw new RuntimeException("'" + notExpectedString 200 + "' found in stderr \n"); 201 } 202 return this; 203 } 204 205 /** 206 * Verify that the stdout and stderr contents of output buffer matches the 207 * pattern 208 * 209 * @param pattern 210 * @throws RuntimeException 211 * If the pattern was not found 212 */ 213 public OutputAnalyzer shouldMatch(String pattern) { 214 Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) 215 .matcher(getStdout()); 216 Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) 217 .matcher(getStderr()); 218 if (!stdoutMatcher.find() && !stderrMatcher.find()) { 219 reportDiagnosticSummary(); 220 throw new RuntimeException("'" + pattern 221 + "' missing from stdout/stderr \n"); 222 } 223 return this; 224 } 225 226 /** 227 * Verify that the stdout contents of output buffer matches the pattern 228 * 229 * @param pattern 230 * @throws RuntimeException 231 * If the pattern was not found 232 */ 233 public OutputAnalyzer stdoutShouldMatch(String pattern) { 234 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( 235 getStdout()); 236 if (!matcher.find()) { 237 reportDiagnosticSummary(); 238 throw new RuntimeException("'" + pattern 239 + "' missing from stdout \n"); 240 } 241 return this; 242 } 243 244 /** 245 * Verify that the stderr contents of output buffer matches the pattern 246 * 247 * @param pattern 248 * @throws RuntimeException 249 * If the pattern was not found 250 */ 251 public OutputAnalyzer stderrShouldMatch(String pattern) { 252 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( 253 getStderr()); 254 if (!matcher.find()) { 255 reportDiagnosticSummary(); 256 throw new RuntimeException("'" + pattern 257 + "' missing from stderr \n"); 258 } 259 return this; 260 } 261 262 /** 263 * Verify that the stdout and stderr contents of output buffer does not 264 * match the pattern 265 * 266 * @param pattern 267 * @throws RuntimeException 268 * If the pattern was found 269 */ 270 public OutputAnalyzer shouldNotMatch(String pattern) { 271 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( 272 getStdout()); 273 if (matcher.find()) { 274 reportDiagnosticSummary(); 275 throw new RuntimeException("'" + pattern + "' found in stdout: '" 276 + matcher.group() + "' \n"); 277 } 278 matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(getStderr()); 279 if (matcher.find()) { 280 reportDiagnosticSummary(); 281 throw new RuntimeException("'" + pattern + "' found in stderr: '" 282 + matcher.group() + "' \n"); 283 } 284 return this; 285 } 286 287 /** 288 * Verify that the stdout contents of output buffer does not match the 289 * pattern 290 * 291 * @param pattern 292 * @throws RuntimeException 293 * If the pattern was found 294 */ 295 public OutputAnalyzer stdoutShouldNotMatch(String pattern) { 296 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( 297 getStdout()); 298 if (matcher.find()) { 299 reportDiagnosticSummary(); 300 throw new RuntimeException("'" + pattern + "' 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 311 * If the pattern was found 312 */ 313 public OutputAnalyzer stderrShouldNotMatch(String pattern) { 314 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( 315 getStderr()); 316 if (matcher.find()) { 317 reportDiagnosticSummary(); 318 throw new RuntimeException("'" + pattern + "' found in stderr \n"); 319 } 320 return this; 321 } 322 323 /** 324 * Get the captured group of the first string matching the pattern. stderr 325 * is searched before stdout. 326 * 327 * @param pattern 328 * The multi-line pattern to match 329 * @param group 330 * The group to capture 331 * @return The matched string or null if no match was found 332 */ 333 public String firstMatch(String pattern, int group) { 334 Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) 335 .matcher(getStderr()); 336 Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) 337 .matcher(getStdout()); 338 if (stderrMatcher.find()) { 339 return stderrMatcher.group(group); 340 } 341 if (stdoutMatcher.find()) { 342 return stdoutMatcher.group(group); 343 } 344 return null; 345 } 346 347 /** 348 * Get the first string matching the pattern. stderr is searched before 349 * stdout. 350 * 351 * @param pattern 352 * The multi-line pattern to match 353 * @return The matched string or null if no match was found 354 */ 355 public String firstMatch(String pattern) { 356 return firstMatch(pattern, 0); 357 } 358 359 /** 360 * Verify the exit value of the process 361 * 362 * @param expectedExitValue 363 * Expected exit value from process 364 * @throws RuntimeException 365 * If the exit value from the process did not match the expected 366 * value 367 */ 368 public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { 369 if (getExitValue() != expectedExitValue) { 370 reportDiagnosticSummary(); 371 throw new RuntimeException("Expected to get exit value of [" 372 + expectedExitValue + "]\n"); 373 } 374 return this; 375 } 376 377 /** 378 * Report summary that will help to diagnose the problem Currently includes: 379 * - standard input produced by the process under test - standard output - 380 * exit code Note: the command line is printed by the ProcessTools 381 */ 382 private OutputAnalyzer reportDiagnosticSummary() { 383 String msg = " stdout: [" + getStdout() + "];\n" + " stderr: [" + getStderr() 384 + "]\n" + " exitValue = " + getExitValue() + "\n"; 385 386 System.err.println(msg); 387 return this; 388 } 389 390 /** 391 * Get the contents of the output buffer (stdout and stderr) 392 * 393 * @return Content of the output buffer 394 */ 395 public String getOutput() { 396 return getStdout() + getStderr(); 397 } 398 399 /** 400 * Get the contents of the stdout buffer 401 * 402 * @return Content of the stdout buffer 403 */ 404 public String getStdout() { 405 return output == null ? stdout : output.getStdout(); 406 } 407 408 /** 409 * Get the contents of the stderr buffer 410 * 411 * @return Content of the stderr buffer 412 */ 413 public String getStderr() { 414 return output == null ? stderr : output.getStderr(); 415 } 416 417 /** 418 * Get the process exit value 419 * 420 * @return Process exit value 421 */ 422 public int getExitValue() { 423 return output == null ? exitValue : output.getExitValue(); 424 } 425 426 427 /** 428 * Print the stdout buffer to the given {@code PrintStream}. 429 * 430 * @return this OutputAnalyzer 431 */ 432 public OutputAnalyzer outputTo(PrintStream out) { 433 out.println(getStdout()); 434 return this; 435 } 436 437 /** 438 * Print the stderr buffer to the given {@code PrintStream}. 439 * 440 * @return this OutputAnalyzer 441 */ 442 public OutputAnalyzer errorTo(PrintStream out) { 443 out.println(getStderr()); 444 return this; 445 } 446 447 448 /** 449 * Get the contents of the output buffer (stdout and stderr) as list of strings. 450 * Output will be split by system property 'line.separator'. 451 * 452 * @return Contents of the output buffer as list of strings 453 */ 454 public List<String> asLines() { 455 return asLines(getOutput()); 456 } 457 458 private List<String> asLines(String buffer) { 459 List<String> l = new ArrayList<>(); 460 String[] a = buffer.split(Utils.NEW_LINE); 461 for (String string : a) { 462 l.add(string); 463 } 464 return l; 465 } 466 467 /** 468 * Check if there is a line matching {@code pattern} and return its index 469 * 470 * @param pattern Matching pattern 471 * @return Index of first matching line 472 */ 473 private int indexOf(List<String> lines, String pattern) { 474 for (int i = 0; i < lines.size(); i++) { 475 if (lines.get(i).matches(pattern)) { 476 return i; 477 } 478 } 479 return -1; 480 } 481 482 /** 483 * @see #shouldMatchByLine(String, String, String) 484 */ 485 public int shouldMatchByLine(String pattern) { 486 return shouldMatchByLine(null, null, pattern); 487 } 488 489 /** 490 * @see #stdoutShouldMatchByLine(String, String, String) 491 */ 492 public int stdoutShouldMatchByLine(String pattern) { 493 return stdoutShouldMatchByLine(null, null, pattern); 494 } 495 496 /** 497 * @see #shouldMatchByLine(String, String, String) 498 */ 499 public int shouldMatchByLineFrom(String from, String pattern) { 500 return shouldMatchByLine(from, null, pattern); 501 } 502 503 /** 504 * @see #shouldMatchByLine(String, String, String) 505 */ 506 public int shouldMatchByLineTo(String to, String pattern) { 507 return shouldMatchByLine(null, to, pattern); 508 } 509 510 /** 511 * Verify that the stdout and stderr contents of output buffer match the 512 * {@code pattern} line by line. The whole output could be matched or 513 * just a subset of it. 514 * 515 * @param from 516 * The line from where output will be matched. 517 * Set {@code from} to null for matching from the first line. 518 * @param to 519 * The line until where output will be matched. 520 * Set {@code to} to null for matching until the last line. 521 * @param pattern 522 * Matching pattern 523 * @return Count of lines which match the {@code pattern} 524 */ 525 public int shouldMatchByLine(String from, String to, String pattern) { 526 return shouldMatchByLine(getOutput(), from, to, pattern); 527 } 528 529 /** 530 * Verify that the stdout contents of output buffer matches the 531 * {@code pattern} line by line. The whole stdout could be matched or 532 * just a subset of it. 533 * 534 * @param from 535 * The line from where stdout will be matched. 536 * Set {@code from} to null for matching from the first line. 537 * @param to 538 * The line until where stdout will be matched. 539 * Set {@code to} to null for matching until the last line. 540 * @param pattern 541 * Matching pattern 542 * @return Count of lines which match the {@code pattern} 543 */ 544 public int stdoutShouldMatchByLine(String from, String to, String pattern) { 545 return shouldMatchByLine(getStdout(), from, to, pattern); 546 } 547 548 private int shouldMatchByLine(String buffer, String from, String to, String pattern) { 549 List<String> lines = asLines(buffer); 550 551 int fromIndex = 0; 552 if (from != null) { 553 fromIndex = indexOf(lines, from); 554 assertGreaterThan(fromIndex, -1, 555 "The line/pattern '" + from + "' from where the output should match can not be found"); 556 } 557 558 int toIndex = lines.size(); 559 if (to != null) { 560 toIndex = indexOf(lines, to); 561 assertGreaterThan(toIndex, -1, 562 "The line/pattern '" + to + "' until where the output should match can not be found"); 563 } 564 565 List<String> subList = lines.subList(fromIndex, toIndex); 566 int matchedCount = 0; 567 for (String line : subList) { 568 assertTrue(line.matches(pattern), 569 "The line '" + line + "' does not match pattern '" + pattern + "'"); 570 matchedCount++; 571 } 572 573 return matchedCount; 574 } 575 576 }