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.util.Arrays; 28 import java.util.List; 29 import java.util.regex.Matcher; 30 import java.util.regex.Pattern; 31 32 public 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 }