1 /*******************************************************************************
2 * Copyright (c) 2000, 2012 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.jdt.core.tests.util;
15
16 import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
17 import org.eclipse.jdt.core.tests.runtime.*;
18 import java.io.*;
19 import java.net.*;
20 /**
21 * Verifies that the .class files resulting from a compilation can be loaded
22 * in a VM and that they can be run.
23 */
24 public class TestVerifier {
25 public String failureReason;
26
27 boolean reuseVM = true;
28 String[] classpathCache;
29 LocalVirtualMachine vm;
30 StringBuffer outputBuffer;
31 StringBuffer errorBuffer;
32 Socket socket;
TestVerifier(boolean reuseVM)33 public TestVerifier(boolean reuseVM) {
34 this.reuseVM = reuseVM;
35 }
checkBuffers(String outputString, String errorString, String sourceFileName, String expectedOutputString, String expectedErrorStringStart)36 private boolean checkBuffers(String outputString, String errorString,
37 String sourceFileName, String expectedOutputString, String expectedErrorStringStart) {
38 boolean didMatchExpectation = true;
39 String platformIndependantString;
40 this.failureReason = null;
41 if (expectedOutputString != null) {
42 platformIndependantString = Util.convertToIndependantLineDelimiter(outputString.trim());
43 if (!Util.convertToIndependantLineDelimiter(expectedOutputString).equals(platformIndependantString)) {
44 System.out.println(Util.displayString(platformIndependantString, 2));
45 this.failureReason =
46 "Unexpected output running resulting class file for "
47 + sourceFileName
48 + ":\n"
49 + "--[START]--\n"
50 + outputString
51 + "---[END]---\n";
52 didMatchExpectation = false;
53 }
54 }
55 String trimmedErrorString = errorString.trim();
56 if (expectedErrorStringStart != null) {
57 platformIndependantString = Util.convertToIndependantLineDelimiter(trimmedErrorString);
58 if (expectedErrorStringStart.length() == 0 && platformIndependantString.length() > 0 ||
59 !platformIndependantString.startsWith(Util.convertToIndependantLineDelimiter(expectedErrorStringStart))) {
60 /*
61 * This is an opportunistic heuristic for error strings comparison:
62 * - null means skip test;
63 * - empty means exactly empty;
64 * - other means starts with.
65 * If this became insufficient, we could envision using specific
66 * matchers for specific needs.
67 */
68 System.out.println(Util.displayString(platformIndependantString, 2));
69 this.failureReason =
70 "Unexpected error running resulting class file for "
71 + sourceFileName
72 + ":\n"
73 + "--[START]--\n"
74 + errorString
75 + "---[END]---\n";
76 didMatchExpectation = false;
77 }
78 } else if (trimmedErrorString.length() != 0){
79 platformIndependantString = Util.convertToIndependantLineDelimiter(trimmedErrorString);
80 System.out.println(Util.displayString(platformIndependantString, 2));
81 this.failureReason =
82 "Unexpected error running resulting class file for "
83 + sourceFileName
84 + ":\n"
85 + "--[START]--\n"
86 + errorString
87 + "---[END]---\n";
88 didMatchExpectation = false;
89 }
90 return didMatchExpectation;
91 }
92
checkBuffersThrowingError(String errorString, String sourceFileName, String expectedSuccessOutputString)93 private boolean checkBuffersThrowingError(String errorString, String sourceFileName, String expectedSuccessOutputString) {
94
95 if (errorString.length() > 0 && errorString.indexOf(expectedSuccessOutputString) != -1) {
96 return true;
97 }
98
99 this.failureReason =
100 "Expected error not thrown for "
101 + sourceFileName
102 + ":\n"
103 + expectedSuccessOutputString;
104 return false;
105 }
106
compileVerifyTests(String verifierDir)107 private void compileVerifyTests(String verifierDir) {
108 String fullyQualifiedName = VerifyTests.class.getName();
109
110 int lastDot = fullyQualifiedName.lastIndexOf('.');
111 String packageName = fullyQualifiedName.substring(0, lastDot);
112 String simpleName = fullyQualifiedName.substring(lastDot + 1);
113
114 String dirName = verifierDir.replace('\\', '/') + "/" + packageName.replace('.', '/');
115 File dir = new File(dirName.replace('/', File.separatorChar));
116 if (!dir.exists() && !dir.mkdirs()) {
117 System.out.println("Could not create " + dir);
118 return;
119 }
120 String fileName = dir + File.separator + simpleName + ".java";
121 Util.writeToFile(getVerifyTestsCode(), fileName);
122 BatchCompiler.compile("\"" + fileName + "\" -d \"" + verifierDir + "\" -warn:-resource -classpath \"" + Util.getJavaClassLibsAsString() + "\"", new PrintWriter(System.out), new PrintWriter(System.err), null/*progress*/);
123 }
execute(String className, String[] classpaths)124 public void execute(String className, String[] classpaths) {
125 this.outputBuffer = new StringBuffer();
126 this.errorBuffer = new StringBuffer();
127
128 launchAndRun(className, classpaths, null, null);
129 }
130 @Override
finalize()131 protected void finalize() throws Throwable {
132 shutDown();
133 }
getExecutionOutput()134 public String getExecutionOutput(){
135 return this.outputBuffer.toString();
136 }
137
getExecutionError()138 public String getExecutionError(){
139 return this.errorBuffer.toString();
140 }
141 /**
142 * Returns the code of the VerifyTests class.
143 *
144 * IMPORTANT NOTE: DO NOTE EDIT BUT GENERATE INSTEAD (see below)
145 *
146 * To generate:
147 * - export VerifyTests.java to d:/temp
148 * - inspect org.eclipse.jdt.core.tests.util.Util.fileContentToDisplayString("d:/temp/VerifyTests.java", 2, true)
149 */
getVerifyTestsCode()150 private String getVerifyTestsCode() {
151 return
152 "/*******************************************************************************\n" +
153 " * Copyright (c) 2000, 2017 IBM Corporation and others.\n" +
154 " * All rights reserved. This program and the accompanying materials\n" +
155 " * are made available under the terms of the Eclipse Public License v1.0\n" +
156 " * which accompanies this distribution, and is available at\n" +
157 " * http://www.eclipse.org/legal/epl-v10.html\n" +
158 " *\n" +
159 " * Contributors:\n" +
160 " * IBM Corporation - initial API and implementation\n" +
161 " *******************************************************************************/\n" +
162 "package org.eclipse.jdt.core.tests.util;\n" +
163 "\n" +
164 "import java.io.DataInputStream;\n" +
165 "import java.io.DataOutputStream;\n" +
166 "import java.io.File;\n" +
167 "import java.io.FileInputStream;\n" +
168 "import java.io.FileNotFoundException;\n" +
169 "import java.io.IOException;\n" +
170 "import java.io.InputStream;\n" +
171 "import java.lang.reflect.InvocationTargetException;\n" +
172 "import java.lang.reflect.Method;\n" +
173 "import java.net.Socket;\n" +
174 "import java.util.StringTokenizer;\n" +
175 "\n" +
176 "/******************************************************\n" +
177 " *\n" +
178 " * IMPORTANT NOTE: If modifying this class, copy the source to TestVerifier#getVerifyTestsCode()\n" +
179 " * (see this method for details)\n" +
180 " *\n" +
181 " ******************************************************/\n" +
182 "\n" +
183 "public class VerifyTests {\n" +
184 " int portNumber;\n" +
185 " Socket socket;\n" +
186 "\n" +
187 "/**\n" +
188 " * NOTE: Code copied from junit.util.TestCaseClassLoader.\n" +
189 " *\n" +
190 " * A custom class loader which enables the reloading\n" +
191 " * of classes for each test run. The class loader\n" +
192 " * can be configured with a list of package paths that\n" +
193 " * should be excluded from loading. The loading\n" +
194 " * of these packages is delegated to the system class\n" +
195 " * loader. They will be shared across test runs.\n" +
196 " * <p>\n" +
197 " * The list of excluded package paths is specified in\n" +
198 " * a properties file \"excluded.properties\" that is located in\n" +
199 " * the same place as the TestCaseClassLoader class.\n" +
200 " * <p>\n" +
201 " * <b>Known limitation:</b> the VerifyClassLoader cannot load classes\n" +
202 " * from jar files.\n" +
203 " */\n" +
204 "\n" +
205 "\n" +
206 "public class VerifyClassLoader extends ClassLoader {\n" +
207 " /** scanned class path */\n" +
208 " private String[] pathItems;\n" +
209 "\n" +
210 " /** excluded paths */\n" +
211 " private String[] excluded= {};\n" +
212 "\n" +
213 " /**\n" +
214 " * Constructs a VerifyClassLoader. It scans the class path\n" +
215 " * and the excluded package paths\n" +
216 " */\n" +
217 " public VerifyClassLoader() {\n" +
218 " super();\n" +
219 " String classPath= System.getProperty(\"java.class.path\");\n" +
220 " String separator= System.getProperty(\"path.separator\");\n" +
221 "\n" +
222 " // first pass: count elements\n" +
223 " StringTokenizer st= new StringTokenizer(classPath, separator);\n" +
224 " int i= 0;\n" +
225 " while (st.hasMoreTokens()) {\n" +
226 " st.nextToken();\n" +
227 " i++;\n" +
228 " }\n" +
229 " // second pass: split\n" +
230 " this.pathItems= new String[i];\n" +
231 " st= new StringTokenizer(classPath, separator);\n" +
232 " i= 0;\n" +
233 " while (st.hasMoreTokens()) {\n" +
234 " this.pathItems[i++]= st.nextToken();\n" +
235 " }\n" +
236 "\n" +
237 " }\n" +
238 " public java.net.URL getResource(String name) {\n" +
239 " return ClassLoader.getSystemResource(name);\n" +
240 " }\n" +
241 " public InputStream getResourceAsStream(String name) {\n" +
242 " return ClassLoader.getSystemResourceAsStream(name);\n" +
243 " }\n" +
244 " protected boolean isExcluded(String name) {\n" +
245 " // exclude the \"java\" packages.\n" +
246 " // They always need to be excluded so that they are loaded by the system class loader\n" +
247 " if (name.startsWith(\"java\") || name.startsWith(\"[Ljava\"))\n" +
248 " return true;\n" +
249 "\n" +
250 " // exclude the user defined package paths\n" +
251 " for (int i= 0; i < this.excluded.length; i++) {\n" +
252 " if (name.startsWith(this.excluded[i])) {\n" +
253 " return true;\n" +
254 " }\n" +
255 " }\n" +
256 " return false;\n" +
257 " }\n" +
258 " public synchronized Class loadClass(String name, boolean resolve)\n" +
259 " throws ClassNotFoundException {\n" +
260 "\n" +
261 " Class c= findLoadedClass(name);\n" +
262 " if (c != null)\n" +
263 " return c;\n" +
264 " //\n" +
265 " // Delegate the loading of excluded classes to the\n" +
266 " // standard class loader.\n" +
267 " //\n" +
268 " if (isExcluded(name)) {\n" +
269 " try {\n" +
270 " c= findSystemClass(name);\n" +
271 " return c;\n" +
272 " } catch (ClassNotFoundException e) {\n" +
273 " // keep searching\n" +
274 " }\n" +
275 " }\n" +
276 " File file= locate(name);\n" +
277 " if (file == null)\n" +
278 " throw new ClassNotFoundException();\n" +
279 " byte data[]= loadClassData(file);\n" +
280 " c= defineClass(name, data, 0, data.length);\n" +
281 " if (resolve)\n" +
282 " resolveClass(c);\n" +
283 " return c;\n" +
284 " }\n" +
285 " private byte[] loadClassData(File f) throws ClassNotFoundException {\n" +
286 " FileInputStream stream = null;\n" +
287 " try {\n" +
288 " //System.out.println(\"loading: \"+f.getPath());\n" +
289 " stream = new FileInputStream(f);\n" +
290 "\n" +
291 " try {\n" +
292 " byte[] b= new byte[stream.available()];\n" +
293 " stream.read(b);\n" +
294 " return b;\n" +
295 " }\n" +
296 " catch (IOException e) {\n" +
297 " throw new ClassNotFoundException();\n" +
298 " }\n" +
299 " }\n" +
300 " catch (FileNotFoundException e) {\n" +
301 " throw new ClassNotFoundException();\n" +
302 " } finally {\n" +
303 " if (stream != null) {\n" +
304 " try {\n" +
305 " stream.close();\n" +
306 " } catch (IOException e) {\n" +
307 " /* ignore */\n" +
308 " }\n" +
309 " }\n" +
310 " }\n" +
311 " }\n" +
312 " /**\n" +
313 " * Locate the given file.\n" +
314 " * @return Returns null if file couldn't be found.\n" +
315 " */\n" +
316 " private File locate(String fileName) {\n" +
317 " if (fileName != null) {\n" +
318 " fileName= fileName.replace('.', '/')+\".class\";\n" +
319 " File path= null;\n" +
320 " for (int i= 0; i < this.pathItems.length; i++) {\n" +
321 " path= new File(this.pathItems[i], fileName);\n" +
322 " if (path.exists())\n" +
323 " return path;\n" +
324 " }\n" +
325 " }\n" +
326 " return null;\n" +
327 " }\n" +
328 "}\n" +
329 "\n" +
330 "public void loadAndRun(String className) throws Throwable {\n" +
331 " //System.out.println(\"Loading \" + className + \"...\");\n" +
332 " Class testClass = new VerifyClassLoader().loadClass(className);\n" +
333 " //System.out.println(\"Loaded \" + className);\n" +
334 " try {\n" +
335 " Method main = testClass.getMethod(\"main\", new Class[] {String[].class});\n" +
336 " //System.out.println(\"Running \" + className);\n" +
337 " main.invoke(null, new Object[] {new String[] {}});\n" +
338 " //System.out.println(\"Finished running \" + className);\n" +
339 " } catch (NoSuchMethodException e) {\n" +
340 " return;\n" +
341 " } catch (InvocationTargetException e) {\n" +
342 " throw e.getTargetException();\n" +
343 " }\n" +
344 "}\n" +
345 "public static void main(String[] args) throws IOException {\n" +
346 " VerifyTests verify = new VerifyTests();\n" +
347 " verify.portNumber = Integer.parseInt(args[0]);\n" +
348 " verify.run();\n" +
349 "}\n" +
350 "public void run() throws IOException {\n" +
351 " this.socket = new Socket(\"localhost\", this.portNumber);\n" +
352 " this.socket.setTcpNoDelay(true);\n" +
353 "\n" +
354 " DataInputStream in = new DataInputStream(this.socket.getInputStream());\n" +
355 " final DataOutputStream out = new DataOutputStream(this.socket.getOutputStream());\n" +
356 " while (true) {\n" +
357 " final String className = in.readUTF();\n" +
358 " Thread thread = new Thread() {\n" +
359 " public void run() {\n" +
360 " try {\n" +
361 " loadAndRun(className);\n" +
362 " out.writeBoolean(true);\n" +
363 " System.err.println(VerifyTests.class.getName());\n" +
364 " System.out.println(VerifyTests.class.getName());\n" +
365 " } catch (Throwable e) {\n" +
366 " e.printStackTrace();\n" +
367 " try {\n" +
368 " System.err.println(VerifyTests.class.getName());\n" +
369 " System.out.println(VerifyTests.class.getName());\n" +
370 " out.writeBoolean(false);\n" +
371 " } catch (IOException e1) {\n" +
372 " e1.printStackTrace();\n" +
373 " }\n" +
374 " }\n" +
375 " try {\n" +
376 " out.flush();\n" +
377 " } catch (IOException e) {\n" +
378 " e.printStackTrace();\n" +
379 " }\n" +
380 " }\n" +
381 " };\n" +
382 " thread.start();\n" +
383 " }\n" +
384 "}\n" +
385 "}";
386 }
launchAndRun(String className, String[] classpaths, String[] programArguments, String[] vmArguments)387 private void launchAndRun(String className, String[] classpaths, String[] programArguments, String[] vmArguments) {
388 // we won't reuse the vm, shut the existing one if running
389 if (this.vm != null) {
390 try {
391 this.vm.shutDown();
392 } catch (TargetException e) {
393 }
394 }
395 this.classpathCache = null;
396
397 // launch a new one
398 LocalVMLauncher launcher = LocalVMLauncher.getLauncher();
399 launcher.setClassPath(classpaths);
400 launcher.setVMPath(Util.getJREDirectory());
401 if (vmArguments != null) {
402 String[] completeVmArguments = new String[vmArguments.length + 1];
403 System.arraycopy(vmArguments, 0, completeVmArguments, 1, vmArguments.length);
404 completeVmArguments[0] = "-verify";
405 launcher.setVMArguments(completeVmArguments);
406 } else {
407 launcher.setVMArguments(new String[] {"-verify"});
408 }
409 launcher.setProgramClass(className);
410 launcher.setProgramArguments(programArguments);
411 Thread outputThread;
412 Thread errorThread;
413 try {
414 this.vm = launcher.launch();
415 final InputStream input = this.vm.getInputStream();
416 outputThread = new Thread(new Runnable() {
417 @Override
418 public void run() {
419 try {
420 int c = input.read();
421 while (c != -1) {
422 TestVerifier.this.outputBuffer.append((char) c);
423 c = input.read();
424 }
425 } catch(IOException e) {
426 }
427 }
428 });
429 final InputStream errorStream = this.vm.getErrorStream();
430 errorThread = new Thread(new Runnable() {
431 @Override
432 public void run() {
433 try {
434 int c = errorStream.read();
435 while (c != -1) {
436 TestVerifier.this.errorBuffer.append((char) c);
437 c = errorStream.read();
438 }
439 } catch(IOException e) {
440 }
441 }
442 });
443 outputThread.start();
444 errorThread.start();
445 } catch(TargetException e) {
446 throw new Error(e.getMessage());
447 }
448
449 // wait for vm to shut down by itself
450 try {
451 outputThread.join(10000); // we shut VMs down forcefully downstream,
452 errorThread.join(10000); // hence let's have some slack here
453 } catch (InterruptedException e) {
454 }
455 }
launchVerifyTestsIfNeeded(String[] classpaths, String[] vmArguments)456 private void launchVerifyTestsIfNeeded(String[] classpaths, String[] vmArguments) {
457 // determine if we can reuse the vm
458 if (this.vm != null && this.vm.isRunning() && this.classpathCache != null) {
459 if (classpaths.length == this.classpathCache.length) {
460 boolean sameClasspaths = true;
461 for (int i = 0; i < classpaths.length; i++) {
462 if (!this.classpathCache[i].equals(classpaths[i])) {
463 sameClasspaths = false;
464 break;
465 }
466 }
467 if (sameClasspaths) {
468 return;
469 }
470 }
471 }
472
473 // we could not reuse the vm, shut the existing one if running
474 if (this.vm != null) {
475 try {
476 this.vm.shutDown();
477 } catch (TargetException e) {
478 }
479 }
480
481 this.classpathCache = classpaths;
482
483 // launch a new one
484 LocalVMLauncher launcher = LocalVMLauncher.getLauncher();
485 int length = classpaths.length;
486 String[] cp = new String[length + 1];
487 System.arraycopy(classpaths, 0, cp, 0, length);
488 String verifierDir = Util.getOutputDirectory() + File.separator + "verifier";
489 compileVerifyTests(verifierDir);
490 cp[length] = verifierDir;
491 launcher.setClassPath(cp);
492 launcher.setVMPath(Util.getJREDirectory());
493 if (vmArguments != null) {
494 String[] completeVmArguments = new String[vmArguments.length + 1];
495 System.arraycopy(vmArguments, 0, completeVmArguments, 1, vmArguments.length);
496 completeVmArguments[0] = "-verify";
497 launcher.setVMArguments(completeVmArguments);
498 } else {
499 launcher.setVMArguments(new String[] {"-verify"});
500 }
501 launcher.setProgramClass(VerifyTests.class.getName());
502 try (ServerSocket server = new ServerSocket(0)) {
503 int portNumber = server.getLocalPort();
504
505 launcher.setProgramArguments(new String[] {Integer.toString(portNumber)});
506 try {
507 this.vm = launcher.launch();
508 final InputStream input = this.vm.getInputStream();
509 Thread outputThread = new Thread(new Runnable() {
510 @Override
511 public void run() {
512 try {
513 int c = input.read();
514 while (c != -1) {
515 TestVerifier.this.outputBuffer.append((char) c);
516 c = input.read();
517 }
518 } catch(IOException ioEx) {
519 }
520 }
521 });
522 final InputStream errorStream = this.vm.getErrorStream();
523 Thread errorThread = new Thread(new Runnable() {
524 @Override
525 public void run() {
526 try {
527 int c = errorStream.read();
528 while (c != -1) {
529 TestVerifier.this.errorBuffer.append((char) c);
530 c = errorStream.read();
531 }
532 } catch(IOException ioEx) {
533 }
534 }
535 });
536 outputThread.start();
537 errorThread.start();
538 } catch(TargetException e) {
539 throw new Error(e.getMessage());
540 }
541
542 // connect to the vm
543 this.socket = null;
544 boolean isVMRunning = false;
545 do {
546 try {
547 this.socket = server.accept();
548 this.socket.setTcpNoDelay(true);
549 break;
550 } catch (UnknownHostException e) {
551 } catch (IOException e) {
552 }
553 if (this.socket == null) {
554 try {
555 Thread.sleep(100);
556 } catch (InterruptedException e) {
557 }
558 isVMRunning = this.vm.isRunning();
559 }
560 } while (this.socket == null && isVMRunning);
561 } catch (IOException e) {
562 throw new Error(e.getMessage());
563 }
564 }
565 /**
566 * Loads and runs the given class.
567 * Return whether no exception was thrown while running the class.
568 */
loadAndRun(String className)569 private boolean loadAndRun(String className) {
570 if (this.socket != null) {
571 try {
572 DataOutputStream out = new DataOutputStream(this.socket.getOutputStream());
573 out.writeUTF(className);
574 DataInputStream in = new DataInputStream(this.socket.getInputStream());
575 try {
576 boolean result = in.readBoolean();
577 waitForFullBuffers();
578 return result;
579 } catch (SocketException e) {
580 // connection was reset because target program has exited
581 return true;
582 }
583 } catch (IOException e) {
584 e.printStackTrace();
585 }
586 }
587 return true;
588 }
shutDown()589 public void shutDown() {
590 // Close the socket first so that the OS resource has a chance to be freed.
591 if (this.socket != null) {
592 try {
593 this.socket.close();
594 } catch (IOException e) {
595 e.printStackTrace();
596 }
597 }
598 // Wait for the vm to shut down by itself for 2 seconds. If not succesfull, force the shut down.
599 if (this.vm != null) {
600 try {
601 int retry = 0;
602 while (this.vm.isRunning() && (++retry < 20)) {
603 try {
604 Thread.sleep(100);
605 } catch (InterruptedException e) {
606 }
607 }
608 if (this.vm.isRunning()) {
609 this.vm.shutDown();
610 }
611 } catch (TargetException e) {
612 e.printStackTrace();
613 }
614 }
615 }
616 /**
617 * Verify that the class files created for the given test file can be loaded by
618 * a virtual machine.
619 */
verifyClassFiles(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths)620 public boolean verifyClassFiles(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths) {
621 return verifyClassFiles(sourceFilePath, className, expectedSuccessOutputString, "", classpaths, null, null);
622 }
623 /**
624 * Verify that the class files created for the given test file can be loaded by
625 * a virtual machine.
626 */
verifyClassFiles(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths, String[] programArguments, String[] vmArguments)627 public boolean verifyClassFiles(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths, String[] programArguments, String[] vmArguments) {
628 return verifyClassFiles(sourceFilePath, className, expectedSuccessOutputString, "", classpaths, programArguments, vmArguments);
629 }
verifyClassFiles(String sourceFilePath, String className, String expectedOutputString, String expectedErrorStringStart, String[] classpaths, String[] programArguments, String[] vmArguments)630 public boolean verifyClassFiles(String sourceFilePath, String className, String expectedOutputString,
631 String expectedErrorStringStart, String[] classpaths, String[] programArguments, String[] vmArguments) {
632 this.outputBuffer = new StringBuffer();
633 this.errorBuffer = new StringBuffer();
634 if (this.reuseVM && programArguments == null) {
635 launchVerifyTestsIfNeeded(classpaths, vmArguments);
636 loadAndRun(className);
637 } else {
638 launchAndRun(className, classpaths, programArguments, vmArguments);
639 }
640
641 this.failureReason = null;
642 return checkBuffers(this.outputBuffer.toString(), this.errorBuffer.toString(), sourceFilePath, expectedOutputString, expectedErrorStringStart);
643 }
644
645 /**
646 * Verify that the class files created for the given test file can be loaded and run with an expected error contained
647 * in the expectedSuccessOutputString string.
648 */
verifyClassFilesThrowingError(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths, String[] programArguments, String[] vmArguments)649 public boolean verifyClassFilesThrowingError(String sourceFilePath, String className, String expectedSuccessOutputString, String[] classpaths, String[] programArguments, String[] vmArguments) {
650 this.outputBuffer = new StringBuffer();
651 this.errorBuffer = new StringBuffer();
652 if (this.reuseVM && programArguments == null) {
653 launchVerifyTestsIfNeeded(classpaths, vmArguments);
654 loadAndRun(className);
655 } else {
656 launchAndRun(className, classpaths, programArguments, vmArguments);
657 }
658
659 this.failureReason = null;
660 return checkBuffersThrowingError(this.errorBuffer.toString(), sourceFilePath, expectedSuccessOutputString);
661 }
662
663 /**
664 * Wait until there is nothing more to read from the stdout or sterr.
665 */
waitForFullBuffers()666 private void waitForFullBuffers() {
667 String endString = VerifyTests.class.getName();
668 int count = 60;
669 int waitMs = 1;
670 int errorEndStringStart = this.errorBuffer.toString().indexOf(endString);
671 int outputEndStringStart = this.outputBuffer.toString().indexOf(endString);
672 while (errorEndStringStart == -1 || outputEndStringStart == -1) {
673 try {
674 Thread.sleep(waitMs);
675 } catch (InterruptedException e) {
676 } finally {
677 if(waitMs < 100) waitMs *= 2;
678 }
679 if (--count == 0) return;
680 errorEndStringStart = this.errorBuffer.toString().indexOf(endString);
681 outputEndStringStart = this.outputBuffer.toString().indexOf(endString);
682 }
683 this.errorBuffer.setLength(errorEndStringStart);
684 this.outputBuffer.setLength(outputEndStringStart);
685 }
686 }
687