/*******************************************************************************
 * Copyright (c) 2003, 2005 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
 *******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

public class CastTest extends AbstractRegressionTest {
	
public CastTest(String name) {
	super(name);
}
public static Test suite() {

	if (false) {
	   	TestSuite ts;
		//some of the tests depend on the order of this suite.
		ts = new TestSuite();
		ts.addTest(new CastTest("test221"));
		return new RegressionTestSetup(ts, COMPLIANCE_1_4);
	}
	return setupSuite(testClass());
}

/*
 * check extra checkcast (interface->same interface)
 */
public void test001() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {	\n" +
			"    public static void main(String[] args) {	\n" +
			"       Cloneable c1 = new int[0]; \n"+
			"		Cloneable c2 = (Cloneable)c1; \n" +
			"		System.out.print(\"SUCCESS\");	\n" +
			"    }	\n" +
			"}	\n",
		},
		"SUCCESS");

	ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
	String actualOutput = null;
	try {
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator  +"X.class"));
		actualOutput =
			disassembler.disassemble(
				classFileBytes,
				"\n",
				ClassFileBytesDisassembler.DETAILED); 
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
		assertTrue("ClassFormatException", false);
	} catch (IOException e) {
		assertTrue("IOException", false);
	}

	String expectedOutput =
		"  // Method descriptor #15 ([Ljava/lang/String;)V\n" + 
		"  // Stack: 2, Locals: 3\n" + 
		"  public static void main(String[] args);\n" + 
		"     0  iconst_0\n" + 
		"     1  newarray int [10]\n" + 
		"     3  astore_1 [c1]\n" + 
		"     4  aload_1 [c1]\n" + 
		"     5  astore_2 [c2]\n" + 
		"     6  getstatic java.lang.System.out : java.io.PrintStream [21]\n" + 
		"     9  ldc <String \"SUCCESS\"> [23]\n" + 
		"    11  invokevirtual java.io.PrintStream.print(java.lang.String) : void  [29]\n" + 
		"    14  return\n" + 
		"      Line numbers:\n" + 
		"        [pc: 0, line: 3]\n" + 
		"        [pc: 4, line: 4]\n" + 
		"        [pc: 6, line: 5]\n" + 
		"        [pc: 14, line: 6]\n" + 
		"      Local variable table:\n" + 
		"        [pc: 0, pc: 15] local: args index: 0 type: java.lang.String[]\n" + 
		"        [pc: 4, pc: 15] local: c1 index: 1 type: java.lang.Cloneable\n" + 
		"        [pc: 6, pc: 15] local: c2 index: 2 type: java.lang.Cloneable\n";
	int index = actualOutput.indexOf(expectedOutput);
	if (index == -1 || expectedOutput.length() == 0) {
		System.out.println(Util.displayString(actualOutput, 2));
	}
	if (index == -1) {
		assertEquals("Wrong contents", expectedOutput, actualOutput);
	}
}

public void test002() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// standard expressions\n" + 
			"		String s = (String) null;	// UNnecessary\n" + 
			"		String t = (String) \"hello\";	// UNnecessary\n" + 
			"		float f = (float) 12;			// UNnecessary\n" + 
			"		int i = (int)12.0;				//   necessary\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	String s = (String) null;	// UNnecessary\n" + 
		"	           ^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from null to String\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 5)\n" + 
		"	String t = (String) \"hello\";	// UNnecessary\n" + 
		"	           ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n" + 
		"3. ERROR in X.java (at line 6)\n" + 
		"	float f = (float) 12;			// UNnecessary\n" + 
		"	          ^^^^^^^^^^\n" + 
		"Unnecessary cast from int to float\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
public void test003() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// message sends		\n" + 
			"		foo((Object) \"hello\");		//   necessary\n" + 
			"		foo((String) \"hello\");			// UNnecessary\n" + 
			"		foo((Object) null);			//   necessary\n" + 
			"		foo((String) null);				// UNnecessary but keep as useful documentation \n" + 
			"	}\n" + 
			"	static void foo(String s) {\n" + 
			"		System.out.println(\"foo(String):\"+s);\n" + 
			"	}\n" + 
			"	static void foo(Object o) {\n" + 
			"		System.out.println(\"foo(Object):\"+o);\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 5)\n" + 
		"	foo((String) \"hello\");			// UNnecessary\n" + 
		"	    ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
public void test004() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// constructors\n" + 
			"		new X((Object) \"hello\");	//   necessary\n" + 
			"		new X((String) \"hello\");	// UNnecessary\n" + 
			"		new X((Object) null);		//   necessary\n" + 
			"		new X((String) null);		// UNnecessary but keep as useful documentation\n" + 
			"	}\n" + 
			"	X(){}\n" + 
			"	X(String s){\n" + 
			"		System.out.println(\"new X(String):\"+s);\n" + 
			"	}\n" + 
			"	X(Object o){\n" + 
			"		System.out.println(\"new X(Object):\"+o);\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 5)\n" + 
		"	new X((String) \"hello\");	// UNnecessary\n" + 
		"	      ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
public void test005() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// qualified allocations\n" + 
			"		new X().new XM3((Object) \"hello\");	//   necessary\n" + 
			"		new X().new XM3((String) \"hello\");	// UNnecessary\n" + 
			"		new X().new XM3((Object) null);		//   necessary\n" + 
			"		new X().new XM3((String) null);		// UNnecessary but keep as useful documentation\n" + 
			"		new X().new XM3((Object) \"hello\"){};	//   necessary\n" + 
			"		new X().new XM3((String) \"hello\"){};	// UNnecessary\n" + 
			"		new X().new XM3((Object) null){};		//   necessary\n" + 
			"		new X().new XM3((String) null){};		// UNnecessary but keep as useful documentation\n" + 
			"	}\n" + 
			"	X(){}\n" + 
			"	static class XM1 extends X {}\n" + 
			"	static class XM2 extends X {}\n" + 
			"	class XM3 {\n" + 
			"		XM3(String s){\n" + 
			"			System.out.println(\"new XM3(String):\"+s);\n" + 
			"		}\n" + 
			"		XM3(Object o){\n" + 
			"			System.out.println(\"new XM3(Object):\"+o);\n" + 
			"		}\n" + 
			"	}	\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 5)\n" + 
		"	new X().new XM3((String) \"hello\");	// UNnecessary\n" + 
		"	                ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 9)\n" + 
		"	new X().new XM3((String) \"hello\"){};	// UNnecessary\n" + 
		"	                ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
public void _test006() { // TODO (philippe) add support to conditional expression for unnecessary cast
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// ternary operator\n" + 
			"		String s = null, t = null;	\n" +
			"		X x0 = s == t\n" + 
			"			? (X)new XM1()			// UNnecessary\n" + 
			"			: new X();\n" + 
			"		X x1 = s == t \n" + 
			"			? (X)new XM1()			//   necessary\n" + 
			"			: new XM2();\n" + 
			"		X x2 = s == t \n" + 
			"			? new XM1()\n" + 
			"			: (X)new XM2();			//   necessary\n" + 
			"		X x3 = s == t \n" + 
			"			? (X)new XM1()			//   necessary\n" + 
			"			: (X)new XM2();			//   necessary\n" + 
			"	}\n" + 
			"	X(){}\n" + 
			"	static class XM1 extends X {}\n" + 
			"	static class XM2 extends X {}\n" + 
			"}\n"
		},
		"x",
		null,
		true,
		customOptions);
}

public void test007() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	X(){}\n" + 
			"	class XM3 {\n" + 
			"		XM3(String s){\n" + 
			"			System.out.println(\"new XM3(String):\"+s);\n" + 
			"		}\n" + 
			"		XM3(Object o){\n" + 
			"			System.out.println(\"new XM3(Object):\"+o);\n" + 
			"		}\n" + 
			"	}	\n" + 
			"	\n" + 
			"	class XM4 extends XM3 {\n" + 
			"		XM4(String s){\n" + 
			"			super((Object) s); // necessary\n" + 
			"			System.out.println(\"new XM4(String):\"+s);\n" + 
			"		}\n" + 
			"		XM4(Object o){\n" + 
			"			super((String) o); // necessary\n" + 
			"			System.out.println(\"new XM4(Object):\"+o);\n" + 
			"		}\n" + 
			"		XM4(Thread t){\n" + 
			"			super((Object) t); // UNnecessary\n" + 
			"			System.out.println(\"new XM4(Thread):\"+t);\n" + 
			"		}\n" + 
			"		XM4(){\n" + 
			"			super((String)null); // UNnecessary but keep as useful documentation\n" + 
			"			System.out.println(\"new XM4():\");\n" + 
			"		}\n" + 
			"		XM4(int i){\n" + 
			"			super((Object)null); // necessary\n" + 
			"			System.out.println(\"new XM4():\");\n" + 
			"		}\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 22)\n" + 
		"	super((Object) t); // UNnecessary\n" + 
		"	      ^^^^^^^^^^\n" + 
		"Unnecessary cast from Thread to Object\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

public void test008() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		boolean b1 = new XM1() instanceof X; // UNnecessary\n" + 
			"		boolean b2 = new X() instanceof XM1; // necessary\n" + 
			"		boolean b3 = null instanceof X;\n" + 
			"	}\n" + 
			"	static class XM1 extends X {}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	boolean b1 = new XM1() instanceof X; // UNnecessary\n" + 
		"	             ^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"The expression of type X.XM1 is already an instance of type X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

public void test009() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		boolean b1 = ((X) new XM1()) == new X(); // UNnecessary\n" + 
			"		boolean b2 = ((X) new XM1()) == new XM2(); // necessary\n" + 
			"		boolean b3 = ((X) null) == new X(); // UNnecessary\n" + 
			"	}\n" + 
			"	static class XM1 extends X {}\n" + 
			"	static class XM2 extends X {}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	boolean b1 = ((X) new XM1()) == new X(); // UNnecessary\n" + 
		"	             ^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from X.XM1 to X\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 5)\n" + 
		"	boolean b3 = ((X) null) == new X(); // UNnecessary\n" + 
		"	             ^^^^^^^^^^\n" + 
		"Unnecessary cast from null to X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

public void test010() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		long l1 = ((long) 1) + 2L; // UNnecessary\n" + 
			"		long l2 = ((long)1) + 2; // necessary\n" + 
			"		long l3 = 0;" + 
			"		l3 += (long)12; // UNnecessary\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	long l1 = ((long) 1) + 2L; // UNnecessary\n" + 
		"	          ^^^^^^^^^^\n" + 
		"Unnecessary cast from int to long\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 5)\n" + 
		"	long l3 = 0;		l3 += (long)12; // UNnecessary\n" + 
		"	            		      ^^^^^^^^\n" + 
		"Unnecessary cast from int to long\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

public void test011() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		String s1 = ((long) 1) + \"hello\"; // necessary\n" + 
			"		String s2 = ((String)\"hello\") + 2; // UNnecessary\n" + 
			"		String s3 = ((String)null) + null; // necessary\n" + 
			"		String s4 = ((int) (byte)1) + \"hello\"; // necessary\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	String s2 = ((String)\"hello\") + 2; // UNnecessary\n" + 
		"	            ^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
public void test012() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		// message sends		\n" + 
			"		X x = new YM1();	\n" +
			"		foo((X) x);			// UNnecessary\n" + 
			"		foo((XM1) x);	// UNnecessary\n" + 
			"		foo((YM1) x);	// necessary \n" + 
			"	}\n" + 
			"	static void foo(X x) {}\n" + 
			"	static void foo(YM1 ym1) {}\n" + 
			"  static class XM1 extends X {}\n" +
			"  static class YM1 extends XM1 {}\n" +
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 5)\n" + 
		"	foo((X) x);			// UNnecessary\n" + 
		"	    ^^^^^\n" + 
		"Unnecessary cast from X to X\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 6)\n" + 
		"	foo((XM1) x);	// UNnecessary\n" + 
		"	    ^^^^^^^\n" + 
		"Unnecessary cast from X to X.XM1\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=42289
public void test013() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	\n" + 
			"	public static void main(String[] args) {\n" + 
			"		int a = 0, b = 1;\n" + 
			"		long d;\n" + 
			"		d = (long)a; 				// unnecessary\n" + 
			"		d = (long)a + b; 		// necessary \n" + 
			"		d = d + a + (long)b; 	// unnecessary\n" + 
			"	}\n" + 
			"}\n" + 
			"\n",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 6)\n" + 
		"	d = (long)a; 				// unnecessary\n" + 
		"	    ^^^^^^^\n" + 
		"Unnecessary cast from int to long\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 8)\n" + 
		"	d = d + a + (long)b; 	// unnecessary\n" + 
		"	            ^^^^^^^\n" + 
		"Unnecessary cast from int to long\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
// 39925 - Unnecessary instanceof checking leads to a NullPointerException
public void test014() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	boolean b = new Cloneable() {} instanceof Cloneable;\n" + 
			"}"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 2)\n" + 
		"	boolean b = new Cloneable() {} instanceof Cloneable;\n" + 
		"	            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"The expression of type new Cloneable(){} is already an instance of type Cloneable\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
// narrowing cast on base types may change value, thus necessary
public void test015() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void foo() {	\n" +
			"    int lineCount = 10; \n" +
			"    long time = 1000; \n" +
			"    double linePerSeconds1 = ((int) (lineCount * 10000.0 / time)) / 10.0; // necessary \n" +
			"    double linePerSeconds2 = ((double) (lineCount * 10000.0 / time)) / 10.0; // UNnecessary \n" +
			"  } \n" +
			"}"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 6)\n" + 
		"	double linePerSeconds2 = ((double) (lineCount * 10000.0 / time)) / 10.0; // UNnecessary \n" + 
		"	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from double to double\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
// narrowing cast on base types may change value, thus necessary
public void test016() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void foo() {	\n" +
			"    int lineCount = 10; \n" +
			"    long time = 1000; \n" +
			"    print((int) (lineCount * 10000.0 / time)); // necessary \n" +
			"    print((double) (lineCount * 10000.0 / time)); // UNnecessary \n" +
			"  } \n" +
			"  void print(double d) {}  \n" +
			"}"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 6)\n" + 
		"	print((double) (lineCount * 10000.0 / time)); // UNnecessary \n" + 
		"	      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from double to double\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
//fault tolerance (40288)
public void test017() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void bar() {\n" + 
			"		foo((X) this);\n" + 
			"		foo((X) zork());\n" + // unbound #zork() should not cause NPE
			"	}\n" + 
			"	void foo(X x) {\n" + 
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	foo((X) this);\n" + 
		"	    ^^^^^^^^\n" + 
		"Unnecessary cast from X to X\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 4)\n" + 
		"	foo((X) zork());\n" + 
		"	        ^^^^\n" + 
		"The method zork() is undefined for the type X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
//fault tolerance (40423)
public void test018() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"class Y {\n" +
			"	static Y[] foo(int[] tab) {\n" +
			"		return null;\n" +
			"	}\n" +
			"}\n" +
			"public class X extends Y {\n" + 
			"	Y[] bar() {\n" +
			"		return (Y[]) Y.foo(new double[] {});\n" + // no cast warning until method is applicable
			"	}\n" +
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 8)\n" + 
		"	return (Y[]) Y.foo(new double[] {});\n" + 
		"	               ^^^\n" + 
		"The method foo(int[]) in the type Y is not applicable for the arguments (double[])\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
//fault tolerance (40288)
public void tes019() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void bar() {\n" + 
			"		X x1 =(X) this;\n" + 
			"		X x2 = (X) zork();\n" + // unbound #zork() should not cause NPE
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	X x1 =(X) this;\n" + 
		"	      ^^^^^^^^\n" + 
		"Unnecessary cast to type X for expression of type X\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 4)\n" + 
		"	X x2 = (X) zork();\n" + 
		"	           ^^^^\n" + 
		"The method zork() is undefined for the type X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
//fault tolerance 
public void test020() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void bar() {\n" +
			"		long l = (long)zork() + 2;\n" + 
			"	}\n" +
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	long l = (long)zork() + 2;\n" + 
		"	               ^^^^\n" + 
		"The method zork() is undefined for the type X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}

// unnecessary cast diagnosis should also consider receiver type (40572)
public void test021() { 
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"p1/A.java",
			"package p1;\n" + 
			"public class A {\n" + 
			"	public class Member1 {}\n" + 
			"	public class Member2 {}\n" + 
			"	class Member3 {}\n" + 
			"   public static class Member4 {\n" +
			"	   public static class M4Member {}\n" + 
			"   }\n" +
			"}\n",
			"p2/B.java",
			"package p2;\n" + 
			"import p1.A;\n" +
			"public class B extends A {\n" + 
			"	public class Member1 {}\n" + 
			"}\n",
			"p1/C.java",
			"package p1;\n" + 
			"import p2.B;\n" +
			"public class C extends B {\n" + 
			"	void baz(B b) {\n" + 
			"		((A)b).new Member1(); // necessary since would bind to B.Member instead\n" +
			"		((A)b).new Member2(); // UNnecessary\n" +
			"		((A)b).new Member3(); // necessary since visibility issue\n" +
			"		((A)b).new Member4().new M4Member(); // fault tolerance\n" +
			"		((A)zork()).new Member1(); // fault-tolerance\n" +
			"		// anonymous\n"+
			"		((A)b).new Member1(){}; // necessary since would bind to B.Member instead\n" +
			"		((A)b).new Member2(){}; // UNnecessary\n" +
			"		((A)b).new Member3(){}; // necessary since visibility issue\n" +
			"		((A)b).new Member4().new M4Member(){}; // fault tolerance\n" +
			"		((A)zork()).new Member1(){}; // fault-tolerance\n" +
			"	}\n" + 
			"}\n",
		},
		"----------\n" + 
		"1. ERROR in p1\\C.java (at line 6)\n" + 
		"	((A)b).new Member2(); // UNnecessary\n" + 
		"	^^^^^^\n" + 
		"Unnecessary cast from B to A\n" + 
		"----------\n" + 
		"2. ERROR in p1\\C.java (at line 8)\n" + 
		"	((A)b).new Member4().new M4Member(); // fault tolerance\n" + 
		"	^^^^^^\n" + 
		"Unnecessary cast from B to A\n" + 
		"----------\n" + 
		"3. ERROR in p1\\C.java (at line 9)\n" + 
		"	((A)zork()).new Member1(); // fault-tolerance\n" + 
		"	    ^^^^\n" + 
		"The method zork() is undefined for the type C\n" + 
		"----------\n" + 
		"4. ERROR in p1\\C.java (at line 12)\n" + 
		"	((A)b).new Member2(){}; // UNnecessary\n" + 
		"	^^^^^^\n" + 
		"Unnecessary cast from B to A\n" + 
		"----------\n" + 
		"5. ERROR in p1\\C.java (at line 14)\n" + 
		"	((A)b).new Member4().new M4Member(){}; // fault tolerance\n" + 
		"	^^^^^^\n" + 
		"Unnecessary cast from B to A\n" + 
		"----------\n" + 
		"6. ERROR in p1\\C.java (at line 15)\n" + 
		"	((A)zork()).new Member1(){}; // fault-tolerance\n" + 
		"	    ^^^^\n" + 
		"The method zork() is undefined for the type C\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
// unnecessary cast diagnosis should tolerate array receiver type (40752)
public void test022() { 
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	customOptions.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, CompilerOptions.IGNORE);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {	\n" +
			"  void foo(java.util.Map map){ \n" +
			"    int[] fillPattern = new int[0]; \n" +
			"    if (fillPattern.equals((int[])map.get(\"x\"))) { \n" +
			"    }  \n" +
			"  } \n"+
			"} \n",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	if (fillPattern.equals((int[])map.get(\"x\"))) { \n" + 
		"	                       ^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from Object to int[]\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
		
// unnecessary cast diagnosis should tolerate array receiver type (40752)
public void test023() { 
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"\n" + 
			"	public static void main(String[] args) {\n" + 
			"		final long lgLow32BitMask1 = ~(~((long) 0) << 32);		// necessary\n" + 
			"		final long lgLow32BitMask2 = ~(~0 << 32);					// necessary\n" + 
			"		final long lgLow32BitMask3 = ~(~((long) 0L) << 32);	// unnecessary\n" + 
			"		final long lgLow32BitMask4 = ~(~((int) 0L) << 32);		// necessary\n" + 
			"		System.out.println(\"lgLow32BitMask1: \"+lgLow32BitMask1);\n" + 
			"		System.out.println(\"lgLow32BitMask2: \"+lgLow32BitMask2);\n" + 
			"	}\n" + 
			"}",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 6)\n" + 
		"	final long lgLow32BitMask3 = ~(~((long) 0L) << 32);	// unnecessary\n" + 
		"	                                ^^^^^^^^^^^\n" + 
		"Unnecessary cast from long to long\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}		

// unnecessary cast diagnosis for message receiver (44400)
public void test024() { 
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public void foo(Object bar) {\n" + 
			"		System.out.println(((Object) bar).toString());\n" + 
			"	}\n" + 
			"}",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 3)\n" + 
		"	System.out.println(((Object) bar).toString());\n" + 
		"	                   ^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from Object to Object\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}		

// unnecessary cast diagnosis for message receiver (44400)
// variation with field access
public void test025() { 
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	int i;\n" + 
			"	public void foo(X bar) {\n" + 
			"		System.out.println(((X) bar).i);\n" + 
			"	}\n" + 
			"}",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	System.out.println(((X) bar).i);\n" + 
		"	                   ^^^^^^^^^\n" + 
		"Unnecessary cast from X to X\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}	
/*
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=47074
 */
public void test026() { 
	
	CompilerOptions options = new CompilerOptions(getCompilerOptions());
	if (options.sourceLevel < ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" + 
				"  public static void main(String[] args) {\n" + 
				"    A a = null;\n" + 
				"    B b = (B) a;\n" + 
				"  }\n" + 
				"}\n" + 
				"interface A {\n" + 
				"  void doSomething();\n" + 
				"}\n" + 
				"interface B {\n" + 
				"  int doSomething();\n" + 
				"}",
			},
			"----------\n" + 
			"1. ERROR in X.java (at line 4)\n" + 
			"	B b = (B) a;\n" + 
			"	      ^^^^^\n" + 
			"Cannot cast from A to B\n" + 
			"----------\n");
		return;
	}
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"  public static void main(String[] args) {\n" + 
			"    A a = null;\n" + 
			"    B b = (B) a;\n" + 
			"  }\n" + 
			"}\n" + 
			"interface A {\n" + 
			"  void doSomething();\n" + 
			"}\n" + 
			"interface B {\n" + 
			"  int doSomething();\n" + 
			"}",
		},
		"");
	
}
/*
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=47074
 */
public void test027() { 
	CompilerOptions options = new CompilerOptions(getCompilerOptions());
	if (options.sourceLevel < ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" + 
				"  public static void main(String[] args) {\n" + 
				"    A a = null;\n" + 
				"    boolean b = a instanceof B;\n" + 
				"  }\n" + 
				"}\n" + 
				"interface A {\n" + 
				"  void doSomething();\n" + 
				"}\n" + 
				"interface B {\n" + 
				"  int doSomething();\n" + 
				"}",
			},
			"----------\n" + 
			"1. ERROR in X.java (at line 4)\n" + 
			"	boolean b = a instanceof B;\n" + 
			"	            ^^^^^^^^^^^^^^\n" + 
			"Incompatible conditional operand types A and B\n" + 
			"----------\n");
		return;
	}
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"  public static void main(String[] args) {\n" + 
			"    A a = null;\n" + 
			"    boolean b = a instanceof B;\n" + 
			"  }\n" + 
			"}\n" + 
			"interface A {\n" + 
			"  void doSomething();\n" + 
			"}\n" + 
			"interface B {\n" + 
			"  int doSomething();\n" + 
			"}",
		},
		"");
}
/*
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=47074
 */
public void test028() {
	CompilerOptions options = new CompilerOptions(getCompilerOptions());
	if (options.sourceLevel < ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" + 
				"  public static void main(String[] args) {\n" + 
				"    A a = null;\n" + 
				"    B b = null;\n" + 
				"    boolean c = a == b;\n" + 
				"  }\n" + 
				"}\n" + 
				"interface A {\n" + 
				"  void doSomething();\n" + 
				"}\n" + 
				"interface B {\n" + 
				"  int doSomething();\n" + 
				"}",
			},
			"----------\n" + 
			"1. ERROR in X.java (at line 5)\n" + 
			"	boolean c = a == b;\n" + 
			"	            ^^^^^^\n" + 
			"Incompatible operand types A and B\n" + 
			"----------\n");
		return;
	}
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"  public static void main(String[] args) {\n" + 
			"    A a = null;\n" + 
			"    B b = null;\n" + 
			"    boolean c = a == b;\n" + 
			"  }\n" + 
			"}\n" + 
			"interface A {\n" + 
			"  void doSomething();\n" + 
			"}\n" + 
			"interface B {\n" + 
			"  int doSomething();\n" + 
			"}",
		},
		"");
	
}

/*
 * verify error when assigning null to array
 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=26903
 */
public void test029() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {	\n" +
			"    public static void main(String[] args) {	\n" +
			"		try {	\n" +
			"		    char[][] qName;	\n" +
			"			qName = null;	\n" +
			"			qName[0] = new char[1];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"		    char[][] qName;	\n" +
			"			qName = (char[][])null;	\n" +
			"			qName[0] = new char[1];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"		    char[][] qName;	\n" +
			"			qName = (char[][])(char[][])(char[][])null;	\n" +
			"			qName[0] = new char[2];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"		    char[][] qName;	\n" +
			"			qName = args.length > 1 ? new char[1][2] : null;	\n" +
			"			qName[0] = new char[3];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		System.out.println(\"SUCCESS\");	\n"+
			"	}	\n" +
			"}	\n",
		},
	"SUCCESS");
}

/*
 * verify error when assigning null to array
 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=26903
 */
public void test030() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {	\n" +
			"    public static void main(String[] args) {	\n" +
			"		try {	\n" +
			"			char[][] qName = null;	\n" +
			"			qName[0] = new char[1];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = (char[][])null;	\n" +
			"			qName[0] = new char[1];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = (char[][])(char[][])(char[][])null;	\n" +
			"			qName[0] = new char[2];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = args.length > 1 ? new char[1][2] : null;	\n" +
			"			qName[0] = new char[3];	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		System.out.println(\"SUCCESS\");	\n"+
			"	}	\n" +
			"}	\n",
		},
	"SUCCESS");
}

/*
 * verify error when assigning null to array
 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=26903
 */
public void test031() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {	\n" +
			"    public static void main(String[] args) {	\n" +
			"		try {	\n" +
			"			char[][] qName = null;	\n" +
			"			setName(qName[0]);	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = (char[][])null;	\n" +
			"			setName(qName[0]);	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = (char[][])(char[][])(char[][])null;	\n" +
			"			setName(qName[0]);	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		try {	\n" +
			"			char[][] qName = args.length > 1 ? new char[1][2] : null;	\n" +
			"			setName(qName[0]);	\n" +
			"		} catch(Exception e){	\n" +
			"		}	\n" +
			"		System.out.println(\"SUCCESS\");	\n"+
			"	}	\n" +
			"	static void setName(char[] name) {	\n"+
			"	}	\n" +
			"}	\n",
		},
	"SUCCESS");
}
/*
 * verify error when assigning null to array
 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=26903
 */
public void test032() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public class X {\n" +
			"    public static void main(String[] args) {\n" +
			"			try {\n" +
			"				((int[]) null)[0] = 0;\n" +
			"				((int[]) null)[0] += 1;\n" +
			"				((int[]) null)[0] ++;\n" +
			"			} catch (NullPointerException e) {\n" +
			"				System.out.print(\"SUCCESS\");\n" +
			"			}\n" +
			"	}\n" +
			"}\n",
		},
	"SUCCESS");
}

/*
 * unused cast diagnosis
 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=54763
 */
public void test033() {
	Map customOptions = getCompilerOptions();
	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
	this.runNegativeTest(
		new String[] {
			"X.java",
			"import java.util.ArrayList;\n" + 
			"import java.util.List;\n" + 
			"\n" + 
			"public class X {\n" + 
			"    public static void main(String [] args) {\n" + 
			"        List list = (List) new ArrayList();\n" + 
			"        list = (List) new ArrayList();\n" + 
			"        \n" + 
			"        String s = (String) \"hello\";\n" + 
			"        s += (List) new ArrayList();\n" + 
			"        \n" + 
			"        ArrayList alist = new ArrayList();\n" + 
			"        List list2 = (List) alist;\n" + 
			"        list2 = (List) alist;\n" + 
			"        \n" + 
			"        String s2 = (String) \"hello\";\n" + 
			"        s2 += (List) alist;\n" + 
			"    }\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 6)\n" + 
		"	List list = (List) new ArrayList();\n" + 
		"	            ^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 7)\n" + 
		"	list = (List) new ArrayList();\n" + 
		"	       ^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n" + 
		"3. ERROR in X.java (at line 9)\n" + 
		"	String s = (String) \"hello\";\n" + 
		"	           ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n" + 
		"4. ERROR in X.java (at line 10)\n" + 
		"	s += (List) new ArrayList();\n" + 
		"	     ^^^^^^^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n" + 
		"5. ERROR in X.java (at line 13)\n" + 
		"	List list2 = (List) alist;\n" + 
		"	             ^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n" + 
		"6. ERROR in X.java (at line 14)\n" + 
		"	list2 = (List) alist;\n" + 
		"	        ^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n" + 
		"7. ERROR in X.java (at line 16)\n" + 
		"	String s2 = (String) \"hello\";\n" + 
		"	            ^^^^^^^^^^^^^^^^\n" + 
		"Unnecessary cast from String to String\n" + 
		"----------\n" + 
		"8. ERROR in X.java (at line 17)\n" + 
		"	s2 += (List) alist;\n" + 
		"	      ^^^^^^^^^^^^\n" + 
		"Unnecessary cast from ArrayList to List\n" + 
		"----------\n",
		null,
		true,
		customOptions);
}
/*
 * check non insertion of checkcast for unnecessary cast to interfaces
 * (same test case as test033)
 */
public void test034() {
	this.runConformTest(
		new String[] {
			"X.java",
			"import java.util.ArrayList;\n" + 
			"import java.util.List;\n" + 
			"\n" + 
			"public class X {\n" + 
			"    public static void main(String [] args) {\n" + 
			"        List list = (List) new ArrayList();\n" + 
			"        list = (List) new ArrayList();\n" + 
			"        \n" + 
			"        ArrayList alist = new ArrayList();\n" + 
			"        List list2 = (List) alist;\n" + 
			"        list2 = (List) alist;\n" + 
			"        \n" + 
			"       System.out.println(\"SUCCESS\");\n" +
			"    }\n" + 
			"}\n",
		},
		"SUCCESS");

	ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
	String actualOutput = null;
	try {
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator  +"X.class"));
		actualOutput =
			disassembler.disassemble(
				classFileBytes,
				"\n",
				ClassFileBytesDisassembler.DETAILED); 
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
		assertTrue("ClassFormatException", false);
	} catch (IOException e) {
		assertTrue("IOException", false);
	}

	String expectedOutput =
		"  // Method descriptor #15 ([Ljava/lang/String;)V\n" + 
		"  // Stack: 2, Locals: 4\n" + 
		"  public static void main(String[] args);\n" + 
		"     0  new java.util.ArrayList [17]\n" + 
		"     3  dup\n" + 
		"     4  invokespecial java.util.ArrayList() [18]\n" + 
		"     7  astore_1 [list]\n" + 
		"     8  new java.util.ArrayList [17]\n" + 
		"    11  dup\n" + 
		"    12  invokespecial java.util.ArrayList() [18]\n" + 
		"    15  astore_1 [list]\n" + 
		"    16  new java.util.ArrayList [17]\n" + 
		"    19  dup\n" + 
		"    20  invokespecial java.util.ArrayList() [18]\n" + 
		"    23  astore_2 [alist]\n" + 
		"    24  aload_2 [alist]\n" + 
		"    25  astore_3 [list2]\n" + 
		"    26  aload_2 [alist]\n" + 
		"    27  astore_3 [list2]\n" + 
		"    28  getstatic java.lang.System.out : java.io.PrintStream [24]\n" + 
		"    31  ldc <String \"SUCCESS\"> [26]\n" + 
		"    33  invokevirtual java.io.PrintStream.println(java.lang.String) : void  [32]\n" + 
		"    36  return\n" + 
		"      Line numbers:\n" + 
		"        [pc: 0, line: 6]\n" + 
		"        [pc: 8, line: 7]\n" + 
		"        [pc: 16, line: 9]\n" + 
		"        [pc: 24, line: 10]\n" + 
		"        [pc: 26, line: 11]\n" + 
		"        [pc: 28, line: 13]\n" + 
		"        [pc: 36, line: 14]\n" + 
		"      Local variable table:\n" + 
		"        [pc: 0, pc: 37] local: args index: 0 type: java.lang.String[]\n" + 
		"        [pc: 8, pc: 37] local: list index: 1 type: java.util.List\n" + 
		"        [pc: 24, pc: 37] local: alist index: 2 type: java.util.ArrayList\n" + 
		"        [pc: 26, pc: 37] local: list2 index: 3 type: java.util.List\n";
	int index = actualOutput.indexOf(expectedOutput);
	if (index == -1 || expectedOutput.length() == 0) {
		System.out.println(Util.displayString(actualOutput, 2));
	}
	if (index == -1) {
		assertEquals("Wrong contents", expectedOutput, actualOutput);
	}
}
// javac incorrectly accepts it
public void test035() {
	this.runNegativeTest(
		new String[] {
			"Test231.java",
			"public class Test231 implements Test231i\n" + 
			"{\n" + 
			"	void	foo()\n" + 
			"	{\n" + 
			"		new Object()\n" + 
			"		{\n" + 
			"			Test231i	bar()\n" + 
			"			{\n" + 
			"				return	(Test231i)this;\n" + 
			"			}\n" + 
			"		};\n" + 
			"	}\n" + 
			"}\n" + 
			"\n" + 
			"\n" + 
			"interface Test231i\n" + 
			"{\n" + 
			"}\n",
		},
		"----------\n" + 
		"1. ERROR in Test231.java (at line 9)\n" + 
		"	return	(Test231i)this;\n" + 
		"	      	^^^^^^^^^^^^^^\n" + 
		"Cannot cast from new Object(){} to Test231i\n" + 
		"----------\n");
}
public void test036() {
	this.runConformTest(
		new String[] {
			"X.java",
			"public final class X {\n" + 
			"	private static final boolean DO_BUG = true;\n" + 
			"\n" + 
			"	// Workaround: cast null to Base\n" + 
			"	private static Base base = DO_BUG ?\n" + 
			"	// (Base)null\n" + 
			"			null : new Base() {\n" + 
			"				public final String test() {\n" + 
			"					return (\"anonymous\");\n" + 
			"				}\n" + 
			"			};\n" + 
			"\n" + 
			"	private X() {\n" + 
			"	}\n" + 
			"\n" + 
			"	public static void main(String[] argv) {\n" + 
			"		if (base == null)\n" + 
			"			System.out.println(\"no base\");\n" + 
			"		else\n" + 
			"			System.out.println(base.test());\n" + 
			"	}\n" + 
			"\n" + 
			"	private static abstract class Base {\n" + 
			"		public Base() {\n" + 
			"		}\n" + 
			"\n" + 
			"		public abstract String test();\n" + 
			"	}\n" + 
			"}\n",
		},
		"no base");
}
public void test037() {
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	public static void main(String[] args) {\n" + 
			"		Integer[] integers = {};\n" + 
			"		int[] ints = (int[]) integers;\n" + 
			"	}\n" + 
			"}\n",
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	int[] ints = (int[]) integers;\n" + 
		"	             ^^^^^^^^^^^^^^^^\n" + 
		"Cannot cast from Integer[] to int[]\n" + 
		"----------\n");
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=101208
public void test038() {
	this.runNegativeTest(
		new String[] {
			"X.java",
			"public class X {\n" + 
			"	void foo() {\n" + 
			"		System.out.println(null instanceof Object);\n" + 
			"      Zork z;\n" +
			"	}\n" + 
			"}\n"
		},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\r\n" + 
		"	Zork z;\r\n" + 
		"	^^^^\n" + 
		"Zork cannot be resolved to a type\n" + 
		"----------\n");
}

public static Class testClass() {
	return CastTest.class;
}
}
