1 /* 2 * Copyright (c) 2013, 2015, 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 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 private 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 }