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 com.oracle.java.testlibrary; 25 26 import java.io.IOException; 27 import java.util.Arrays; 28 import java.io.File; 29 import java.nio.file.Files; 30 import java.util.List; 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 33 34 public final class OutputAnalyzer { 35 36 private final String stdout; 37 private final String stderr; 38 private final int exitValue; 39 40 /** 41 * Create an OutputAnalyzer, a utility class for verifying output and exit 42 * value from a Process 43 * 44 * @param process Process to analyze 45 * @throws IOException If an I/O error occurs. 46 */ 47 public OutputAnalyzer(Process process) throws IOException { 48 OutputBuffer output = ProcessTools.getOutput(process); 49 exitValue = process.exitValue(); 50 this.stdout = output.getStdout(); 51 this.stderr = output.getStderr(); 52 } 53 54 /** 55 * Create an OutputAnalyzer, a utility class for verifying output 56 * loaded from the specified file. 57 * 58 * The loaded output can be retrived with getStdout or/and getOutput 59 * methods, getStderr always returns an empty string. 60 * 61 * @param file a text file to analyze 62 * @throws IOException If an I/O error occurs. 63 **/ 64 public OutputAnalyzer(File file) throws IOException { 65 this(new String(Files.readAllBytes(file.toPath())), ""); 66 } 67 68 /** 69 * Create an OutputAnalyzer, a utility class for verifying output 70 * 71 * @param buf String buffer to analyze 72 */ 73 public OutputAnalyzer(String buf) { 74 this(buf, buf); 75 } 76 77 /** 78 * Create an OutputAnalyzer, a utility class for verifying output 79 * 80 * @param stdout stdout buffer to analyze 81 * @param stderr stderr buffer to analyze 82 */ 83 public OutputAnalyzer(String stdout, String stderr) { 84 this.stdout = stdout; 85 this.stderr = stderr; 86 exitValue = -1; 87 } 88 89 /** 90 * Verify that the stdout contents of output buffer is empty 91 * 92 * @throws RuntimeException 93 * If stdout was not empty 94 */ 95 public void stdoutShouldBeEmpty() { 96 if (!getStdout().isEmpty()) { 97 reportDiagnosticSummary(); 98 throw new RuntimeException("stdout was not empty"); 99 } 100 } 101 102 /** 103 * Verify that the stderr contents of output buffer is empty 104 * 105 * @throws RuntimeException 106 * If stderr was not empty 107 */ 108 public void stderrShouldBeEmpty() { 109 if (!getStderr().isEmpty()) { 110 reportDiagnosticSummary(); 111 throw new RuntimeException("stderr was not empty"); 112 } 113 } 114 115 /** 116 * Verify that the stdout contents of output buffer is not empty 117 * 118 * @throws RuntimeException 119 * If stdout was empty 120 */ 121 public void stdoutShouldNotBeEmpty() { 122 if (getStdout().isEmpty()) { 123 reportDiagnosticSummary(); 124 throw new RuntimeException("stdout was empty"); 125 } 126 } 127 128 /** 129 * Verify that the stderr contents of output buffer is not empty 130 * 131 * @throws RuntimeException 132 * If stderr was empty 133 */ 134 public void stderrShouldNotBeEmpty() { 135 if (getStderr().isEmpty()) { 136 reportDiagnosticSummary(); 137 throw new RuntimeException("stderr was empty"); 138 } 139 } 140 141 /** 142 * Verify that the stdout and stderr contents of output buffer contains the string 143 * 144 * @param expectedString String that buffer should contain 145 * @throws RuntimeException If the string was not found 146 */ 147 public OutputAnalyzer shouldContain(String expectedString) { 148 if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { 149 reportDiagnosticSummary(); 150 throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n"); 151 } 152 return this; 153 } 154 155 /** 156 * Verify that the stdout contents of output buffer contains the string 157 * 158 * @param expectedString String that buffer should contain 159 * @throws RuntimeException If the string was not found 160 */ 161 public OutputAnalyzer stdoutShouldContain(String expectedString) { 162 if (!stdout.contains(expectedString)) { 163 reportDiagnosticSummary(); 164 throw new RuntimeException("'" + expectedString + "' missing from stdout \n"); 165 } 166 return this; 167 } 168 169 /** 170 * Verify that the stderr contents of output buffer contains the string 171 * 172 * @param expectedString String that buffer should contain 173 * @throws RuntimeException If the string was not found 174 */ 175 public OutputAnalyzer stderrShouldContain(String expectedString) { 176 if (!stderr.contains(expectedString)) { 177 reportDiagnosticSummary(); 178 throw new RuntimeException("'" + expectedString + "' missing from stderr \n"); 179 } 180 return this; 181 } 182 183 /** 184 * Verify that the stdout and stderr contents of output buffer does not contain the string 185 * 186 * @param expectedString String that the buffer should not contain 187 * @throws RuntimeException If the string was found 188 */ 189 public OutputAnalyzer shouldNotContain(String notExpectedString) { 190 if (stdout.contains(notExpectedString)) { 191 reportDiagnosticSummary(); 192 throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); 193 } 194 if (stderr.contains(notExpectedString)) { 195 reportDiagnosticSummary(); 196 throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); 197 } 198 return this; 199 } 200 201 /** 202 * Verify that the stdout contents of output buffer does not contain the string 203 * 204 * @param expectedString String that the buffer should not contain 205 * @throws RuntimeException If the string was found 206 */ 207 public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { 208 if (stdout.contains(notExpectedString)) { 209 reportDiagnosticSummary(); 210 throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); 211 } 212 return this; 213 } 214 215 /** 216 * Verify that the stderr contents of output buffer does not contain the string 217 * 218 * @param expectedString String that the buffer should not contain 219 * @throws RuntimeException If the string was found 220 */ 221 public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { 222 if (stderr.contains(notExpectedString)) { 223 reportDiagnosticSummary(); 224 throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); 225 } 226 return this; 227 } 228 229 /** 230 * Verify that the stdout and stderr contents of output buffer matches 231 * the pattern 232 * 233 * @param pattern 234 * @throws RuntimeException If the pattern was not found 235 */ 236 public OutputAnalyzer shouldMatch(String pattern) { 237 Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); 238 Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); 239 if (!stdoutMatcher.find() && !stderrMatcher.find()) { 240 reportDiagnosticSummary(); 241 throw new RuntimeException("'" + pattern 242 + "' missing from stdout/stderr \n"); 243 } 244 return this; 245 } 246 247 /** 248 * Verify that the stdout contents of output buffer matches the 249 * pattern 250 * 251 * @param pattern 252 * @throws RuntimeException If the pattern was not found 253 */ 254 public OutputAnalyzer stdoutShouldMatch(String pattern) { 255 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); 256 if (!matcher.find()) { 257 reportDiagnosticSummary(); 258 throw new RuntimeException("'" + pattern 259 + "' missing from stdout \n"); 260 } 261 return this; 262 } 263 264 /** 265 * Verify that the stderr contents of output buffer matches the 266 * pattern 267 * 268 * @param pattern 269 * @throws RuntimeException If the pattern was not found 270 */ 271 public OutputAnalyzer stderrShouldMatch(String pattern) { 272 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); 273 if (!matcher.find()) { 274 reportDiagnosticSummary(); 275 throw new RuntimeException("'" + pattern 276 + "' missing from stderr \n"); 277 } 278 return this; 279 } 280 281 /** 282 * Verify that the stdout and stderr contents of output buffer does not 283 * match the pattern 284 * 285 * @param pattern 286 * @throws RuntimeException If the pattern was found 287 */ 288 public OutputAnalyzer shouldNotMatch(String pattern) { 289 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); 290 if (matcher.find()) { 291 reportDiagnosticSummary(); 292 throw new RuntimeException("'" + pattern 293 + "' found in stdout: '" + matcher.group() + "' \n"); 294 } 295 matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); 296 if (matcher.find()) { 297 reportDiagnosticSummary(); 298 throw new RuntimeException("'" + pattern 299 + "' found in stderr: '" + matcher.group() + "' \n"); 300 } 301 return this; 302 } 303 304 /** 305 * Verify that the stdout contents of output buffer does not match the 306 * pattern 307 * 308 * @param pattern 309 * @throws RuntimeException If the pattern was found 310 */ 311 public OutputAnalyzer stdoutShouldNotMatch(String pattern) { 312 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); 313 if (matcher.find()) { 314 reportDiagnosticSummary(); 315 throw new RuntimeException("'" + pattern 316 + "' found in stdout \n"); 317 } 318 return this; 319 } 320 321 /** 322 * Verify that the stderr contents of output buffer does not match the 323 * pattern 324 * 325 * @param pattern 326 * @throws RuntimeException If the pattern was found 327 */ 328 public OutputAnalyzer stderrShouldNotMatch(String pattern) { 329 Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); 330 if (matcher.find()) { 331 reportDiagnosticSummary(); 332 throw new RuntimeException("'" + pattern 333 + "' found in stderr \n"); 334 } 335 return this; 336 } 337 338 /** 339 * Get the captured group of the first string matching the pattern. 340 * stderr is searched before stdout. 341 * 342 * @param pattern The multi-line pattern to match 343 * @param group The group to capture 344 * @return The matched string or null if no match was found 345 */ 346 public String firstMatch(String pattern, int group) { 347 Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); 348 Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); 349 if (stderrMatcher.find()) { 350 return stderrMatcher.group(group); 351 } 352 if (stdoutMatcher.find()) { 353 return stdoutMatcher.group(group); 354 } 355 return null; 356 } 357 358 /** 359 * Get the first string matching the pattern. 360 * stderr is searched before stdout. 361 * 362 * @param pattern The multi-line pattern to match 363 * @return The matched string or null if no match was found 364 */ 365 public String firstMatch(String pattern) { 366 return firstMatch(pattern, 0); 367 } 368 369 /** 370 * Verify the exit value of the process 371 * 372 * @param expectedExitValue Expected exit value from process 373 * @throws RuntimeException If the exit value from the process did not match the expected value 374 */ 375 public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { 376 if (getExitValue() != expectedExitValue) { 377 reportDiagnosticSummary(); 378 throw new RuntimeException("Expected to get exit value of [" 379 + expectedExitValue + "]\n"); 380 } 381 return this; 382 } 383 384 385 /** 386 * Report summary that will help to diagnose the problem 387 * Currently includes: 388 * - standard input produced by the process under test 389 * - standard output 390 * - exit code 391 * Note: the command line is printed by the ProcessTools 392 */ 393 private void reportDiagnosticSummary() { 394 String msg = 395 " stdout: [" + stdout + "];\n" + 396 " stderr: [" + stderr + "]\n" + 397 " exitValue = " + getExitValue() + "\n"; 398 399 System.err.println(msg); 400 } 401 402 403 /** 404 * Get the contents of the output buffer (stdout and stderr) 405 * 406 * @return Content of the output buffer 407 */ 408 public String getOutput() { 409 return stdout + stderr; 410 } 411 412 /** 413 * Get the contents of the stdout buffer 414 * 415 * @return Content of the stdout buffer 416 */ 417 public String getStdout() { 418 return stdout; 419 } 420 421 /** 422 * Get the contents of the stderr buffer 423 * 424 * @return Content of the stderr buffer 425 */ 426 public String getStderr() { 427 return stderr; 428 } 429 430 /** 431 * Get the process exit value 432 * 433 * @return Process exit value 434 */ 435 public int getExitValue() { 436 return exitValue; 437 } 438 439 /** 440 * Get the contents of the output buffer (stdout and stderr) as list of strings. 441 * Output will be split by newlines. 442 * 443 * @return Contents of the output buffer as list of strings 444 */ 445 public List<String> asLines() { 446 return asLines(getOutput()); 447 } 448 449 private List<String> asLines(String buffer) { 450 return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)")); 451 } 452 }