blob: f8d70197e5b7a675016ac8d33286698b47343dd6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
* Here we focus on various aspects of the runtime behavior of the generated
* code.
*/
package org.eclipse.wst.jsdt.core.tests.compiler.regression;
import junit.framework.Test;
public class RuntimeTests extends AbstractRegressionTest {
public RuntimeTests(String name) {
super(name);
}
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which does not belong to the class are skipped...
// Only the highest compliance level is run; add the VM argument
// -Dcompliance=1.4 (for example) to lower it if needed
static {
// TESTS_NAMES = new String[] { "test0001" };
// TESTS_NUMBERS = new int[] { 1 };
// TESTS_RANGE = new int[] { 1, -1 };
}
public static Test suite() {
return buildAllCompliancesTestSuite(testClass());
}
public static Class testClass() {
return RuntimeTests.class;
}
// memory exhaustion - try to allocate too big an instance
public void test0001_memory_exhaustion() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
" public static void main(String args[]) {\n" +
" try {" +
" Y y = new Y(Integer.MAX_VALUE);\n" +
" }" +
" catch (OutOfMemoryError e) {\n" +
" System.out.println(\"SUCCESS\");\n" +
" return;\n" +
" }\n" +
" System.out.println(\"FAILURE\");\n" +
" }\n" +
"}\n" +
"class Y {\n" +
" long storage[];\n" +
" Y(int itemsNb) {\n" +
" storage = new long[itemsNb];\n" +
" }\n" +
"}\n"},
"SUCCESS"
);
}
// synchronization - concurrent access to a resource with explicit and
// implicit locks
public void test0500_synchronization() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main (String args[]) {\n" +
" new Lock().implicitLock();\n" +
"}\n" +
"}\n" +
"class Lock extends Thread {\n" +
" byte step = 0;\n" +
" void logStep(String start) {\n" +
" System.out.println(start + \" \" + this.step); //$NON-NLS-1$\n" +
" }\n" +
" public void run() {\n" +
" for (int i = 1; i < 3; i++) {\n" +
" logStep(\"explicit lock\"); //$NON-NLS-1$\n" +
" synchronized (this) {\n" +
" this.step++;\n" +
" notify();\n" +
" while(this.step < 2 * i) {\n" +
" try {\n" +
" wait();\n" +
" } catch (InterruptedException e) {\n" +
" System.out.println(\"EXCEPTION\"); //$NON-NLS-1$\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" synchronized void implicitLock() {\n" +
" this.start();\n" +
" for (int i = 0; i < 2; i++) {\n" +
" while (this.step < 1 + i * 2) {\n" +
" try {\n" +
" wait();\n" +
" } catch (InterruptedException e) {\n" +
" System.out.println(\"EXCEPTION\"); //$NON-NLS-1$\n" +
" }\n" +
" }\n" +
" logStep(\"implicit lock\"); //$NON-NLS-1$\n" +
" this.step++;\n" +
" notify();\n" +
" }\n" +
" return;\n" +
" }\n" +
"}\n"},
"explicit lock 0\n" +
"implicit lock 1\n" +
"explicit lock 2\n" +
"implicit lock 3"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=126712
// reflection - access to a public method of a package visible
// class through a public extending class
public void _test0600_reflection() {
if (COMPLIANCE_1_3.equals(this.complianceLevel) ||
COMPLIANCE_1_4.equals(this.complianceLevel)) {
this.runConformTest(
new String[] {
"X.java",
"import java.lang.reflect.*;\n" +
"import p.*;\n" +
"public class X {\n" +
"static public void main (String args[]) {\n" +
" Y y = new Y();\n" +
" try {\n" +
" Method foo = Y.class.getMethod(\"foo\", null);\n" +
" foo.invoke(y, null);\n" +
" y.foo();\n" +
" }\n" +
" catch (Throwable t) {\n" +
" System.out.println(\"FAILURE: \" + t.getMessage());\n" +
" t.printStackTrace(System.out);\n" +
" }\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y extends Z {\n" +
" /* empty */\n" +
"}\n",
"p/Z.java",
"package p;\n" +
"class Z {\n" +
" public void foo() {\n" +
" System.out.println(\"SUCCESS\"); //$NON-NLS-1$\n" +
" }\n" +
"}\n"},
"SUCCESS\nSUCCESS"
);
}
else {
this.runConformTest(
new String[] {
"X.java",
"import java.lang.reflect.*;\n" +
"import p.*;\n" +
"public class X {\n" +
"static public void main (String args[]) {\n" +
" Y y = new Y();\n" +
" try {\n" +
" Method foo = Y.class.getMethod(\"foo\");\n" +
" foo.invoke(y);\n" +
" y.foo();\n" +
" }\n" +
" catch (Throwable t) {\n" +
" System.out.println(\"FAILURE: \" + t.getMessage());\n" +
" t.printStackTrace(System.out);\n" +
" }\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y extends Z {\n" +
" /* empty */\n" +
"}\n",
"p/Z.java",
"package p;\n" +
"class Z {\n" +
" public void foo() {\n" +
" System.out.println(\"SUCCESS\"); //$NON-NLS-1$\n" +
" }\n" +
"}\n"},
"SUCCESS\nSUCCESS"
);
}
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=126712
// reflection - access to a public field of a package visible
// class through a public extending class
public void _test0601_reflection() {
this.runConformTest(
new String[] {
"X.java",
"import java.lang.reflect.*;\n" +
"import p.*;\n" +
"public class X {\n" +
"static public void main (String args[]) {\n" +
" Y y = new Y();\n" +
" try {\n" +
" Field f = Y.class.getField(\"m\");\n" +
" System.out.println(y.m);\n" +
" System.out.println(f.get(y));\n" +
" }\n" +
" catch (Throwable t) {\n" +
" System.out.println(\"FAILURE: \" + t.getMessage());\n" +
" t.printStackTrace(System.out);\n" +
" }\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y extends Z {\n" +
" /* empty */\n" +
"}\n",
"p/Z.java",
"package p;\n" +
"class Z {\n" +
" public String m = \"SUCCESS\";\n" +
"}\n"},
"SUCCESS\nSUCCESS"
);
}
// partial rebuild - method signature changed (return type)
public void test1000_partial_rebuild() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" Z.go();\n" +
"}\n" +
"}\n",
"Z.java",
"public class Z {\n" +
"static public void go() {\n" +
" int flag = 0;\n" +
" try {\n" +
" new Y().random();\n" +
" flag = 1;\n" +
" }\n" +
" catch (NoSuchMethodError e) {\n" +
" flag = 2;\n" +
" }\n" +
" catch (Throwable t) {\n" +
" flag = 3;\n" +
" }\n" +
" System.out.println(flag);\n" +
"}\n" +
"}\n",
"Y.java",
"public class Y {\n" +
"java.util.Random generator = new java.util.Random();" +
"public byte random() {\n" +
" return (byte) (generator.nextInt() % Byte.MAX_VALUE);\n" +
"}\n" +
"}\n",
},
"1");
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" Z.go();\n" +
"}\n" +
"}\n",
"Y.java",
"public class Y {\n" +
"java.util.Random generator = new java.util.Random();" +
"public int random() {\n" + // random now returns an int
" return generator.nextInt();\n" +
"}\n" +
"}\n",
},
"2",
null,
false, // do not purge output directory - pick old version of Z.class
null);
}
// partial rebuild - method signature changed (parameter type)
public void test1001_partial_rebuild() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" Z.go();\n" +
"}\n" +
"}\n",
"Z.java",
"public class Z {\n" +
"static public void go() {\n" +
" byte flag = 0;\n" +
" try {\n" +
" new Y().random(flag);\n" +
" flag = 1;\n" +
" }\n" +
" catch (NoSuchMethodError e) {\n" +
" flag = 2;\n" +
" }\n" +
" catch (Throwable t) {\n" +
" flag = 3;\n" +
" }\n" +
" System.out.println(flag);\n" +
"}\n" +
"}\n",
"Y.java",
"public class Y {\n" +
"public int random(byte seed) {\n" +
" return seed++;\n" +
"}\n" +
"}\n",
},
"1");
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" Z.go();\n" +
"}\n" +
"}\n",
"Y.java",
"public class Y {\n" +
"public int random(int seed) {\n" + // seed now of type int
" return seed++;\n" +
"}\n" +
"}\n",
},
"2",
null,
false, // do not purge output directory - pick old version of Z.class
null);
}
// partial rebuild - method signature changed (visibility)
public void test1002_partial_rebuild() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" new Z().go();\n" +
"}\n" +
"}\n",
"Z.java",
"public class Z extends p.Y {\n" +
" class ZInner extends YInner {\n" +
" // empty\n" +
" }\n" +
"public void go() {\n" +
" byte flag = 0;\n" +
" try {\n" +
" new ZInner().foo();\n" +
" flag = 1;\n" +
" }\n" +
" catch (IllegalAccessError e) {\n" +
" flag = 2;\n" +
" }\n" +
" catch (Throwable t) {\n" +
" flag = 3;\n" +
" }\n" +
" System.out.println(flag);\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public class YInner {\n" +
" public void foo() {\n" +
" return;\n" +
" }\n" +
" }\n" +
"}\n",
},
"1");
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" new Z().go();\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public class YInner {\n" +
" void foo() {\n" + // now foo no more visible (package only)
" return;\n" +
" }\n" +
" }\n" +
"}\n",
},
"2",
null,
false, // do not purge output directory - pick old version of Z.class
null);
}
// partial rebuild - method signature changed (visibility)
public void test1003_partial_rebuild() {
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" new Z().go();\n" +
"}\n" +
"}\n",
"Z.java",
"public class Z extends p.Y {\n" +
" class ZInner extends YInner {\n" +
" // empty\n" +
" }\n" +
"public void go() {\n" +
" byte flag = 0;\n" +
" try {\n" +
" new ZInner().foo();\n" +
" flag = 1;\n" +
" }\n" +
" catch (IllegalAccessError e) {\n" +
" flag = 2;\n" +
" }\n" +
" catch (Throwable t) {\n" +
" flag = 3;\n" +
" }\n" +
" System.out.println(flag);\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public class YInner {\n" +
" public void foo() {\n" +
" return;\n" +
" }\n" +
" }\n" +
"}\n",
},
"1");
this.runConformTest(
new String[] {
"X.java",
"public class X {\n" +
"static public void main(String args[]) {\n" +
" new Z().go();\n" +
"}\n" +
"}\n",
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public class YInner {\n" +
" protected void foo() {\n" +
// now foo no more visible (package + inheriting classes only)
" return;\n" +
" }\n" +
" }\n" +
"}\n",
},
"2",
null,
false, // do not purge output directory - pick old version of Z.class
null);
}
// partial rebuild - extending class now redefines extended class fields and
// methods
// was Compliance_1_x#test009
public void test1004_partial_rebuild() {
this.runConformTest(
new String[] {
"p1/Z.java",
"package p1; \n"+
"public class Z { \n" +
" public static void main(String[] arguments) { \n"+
" Y y = new Y(); \n" +
" System.out.print(y.field); \n" +
" System.out.print(y.staticField); \n" +
" System.out.print(y.method()); \n" +
" System.out.println(y.staticMethod()); \n" +
" } \n"+
"} \n",
"p1/X.java",
"package p1; \n"+
"public class X { \n"+
" public String field = \"X.field-\"; \n" +
" public static String staticField = \"X.staticField-\"; \n" +
" public String method(){ return \"X.method()-\"; } \n" +
" public static String staticMethod(){ return \"X.staticMethod()-\"; } \n" +
"} \n",
"p1/Y.java",
"package p1; \n"+
"public class Y extends X { \n"+
"} \n"
},
"X.field-X.staticField-X.method()-X.staticMethod()-");
String expectedOutput =
this.complianceLevel.equals(COMPLIANCE_1_3) ?
"X.field-X.staticField-Y.method()-X.staticMethod()-" :
"Y.field-Y.staticField-Y.method()-Y.staticMethod()-";
this.runConformTest(
new String[] {
"p1/Y.java",
"package p1; \n"+
"public class Y extends X { \n"+
" public static void main(String[] arguments) { \n"+
" Z.main(arguments); \n" +
" } \n" +
" public String field = \"Y.field-\"; \n" +
" public static String staticField = \"Y.staticField-\"; \n" +
" public String method(){ return \"Y.method()-\"; } \n" +
" public static String staticMethod(){ return \"Y.staticMethod()-\"; } \n" +
"} \n"
},
expectedOutput, // expected output
null, // use default class-path
false, // do not flush previous output dir content
null); // no special vm args
}
}