/*******************************************************************************
 * Copyright (c) 2013, 2014 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
 *		Stephan Herrmann - Contribution for
 *								bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
 *								Bug 454031 - [compiler][null][loop] bug in null analysis; wrong "dead code" detection
 *******************************************************************************/
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 org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

/* See also NullReferenceTests for general null reference tests */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class NullReferenceTestAsserts extends AbstractRegressionTest {
	
// class libraries including org.eclipse.equinox.common
String[] assertLib = null;
public NullReferenceTestAsserts(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[] { "testBug382069" };
//		TESTS_NUMBERS = new int[] { 561 };
//		TESTS_RANGE = new int[] { 1, 2049 };
}

static final String JUNIT_ASSERT_NAME = "junit/framework/Assert.java";
static final String JUNIT_ASSERT_CONTENT = "package junit.framework;\n" +
		"public class Assert {\n" +
		"    static public void assertNull(Object object) {}\n" +
		"    static public void assertNull(String message, Object object) {}\n" +
		"    static public void assertNotNull(Object object) {}\n" +
		"    static public void assertNotNull(String message, Object object) {}\n" +
		"    static public void assertTrue(boolean expression) {}\n" +
		"    static public void assertTrue(String message, boolean expression) {}\n" +
		"    static public void assertFalse(boolean expression) {}\n" +
		"    static public void assertFalse(String message, boolean expression) {}\n" +
		"}\n";

static final String ORG_JUNIT_ASSERT_NAME = "org/junit/Assert.java";
static final String ORG_JUNIT_ASSERT_CONTENT = "package org.junit;\n" +
		"public class Assert {\n" +
		"    static public void assertNull(Object object) {}\n" +
		"    static public void assertNull(String message, Object object) {}\n" +
		"    static public void assertNotNull(Object object) {}\n" +
		"    static public void assertNotNull(String message, Object object) {}\n" +
		"    static public void assertTrue(boolean expression) {}\n" +
		"    static public void assertTrue(String message, boolean expression) {}\n" +
		"    static public void assertFalse(boolean expression) {}\n" +
		"    static public void assertFalse(String message, boolean expression) {}\n" +
		"}\n";

static final String APACHE_VALIDATE_NAME = "org/apache/commons/lang/Validate.java";
static final String APACHE_VALIDATE_CONTENT = "package org.apache.commons.lang;\n" +
		"public class Validate {\n" +
		"    static public void notNull(Object object) {}\n" +
		"    static public void notNull(Object object, String message) {}\n" +
		"    static public void isTrue(boolean expression) {}\n" +
		"    static public void isTrue(boolean expression, String message) {}\n" +
		"    static public void isTrue(boolean expression, String message, double value) {}\n" +
		"    static public void isTrue(boolean expression, String message, long value) {}\n" +
		"    static public void isTrue(boolean expression, String message, Object value) {}\n" +
		"}\n";

static final String APACHE_3_VALIDATE_NAME = "org/apache/commons/lang3/Validate.java";
static final String APACHE_3_VALIDATE_CONTENT = "package org.apache.commons.lang3;\n" +
		"public class Validate {\n" +
		"    static public <T> T notNull(T object) { return object; }\n" +
		"    static public <T> T notNull(T object, String message, Object... values) { return object; }\n" +
		"    static public void isTrue(boolean expression) {}\n" +
		"    static public void isTrue(boolean expression, String message, double value) {}\n" +
		"    static public void isTrue(boolean expression, String message, long value) {}\n" +
		"    static public void isTrue(boolean expression, String message, Object value) {}\n" +
		"}\n";

static final String GOOGLE_PRECONDITIONS_NAME = "com/google/common/base/Preconditions.java";
static final String GOOGLE_PRECONDITIONS_CONTENT = "package com.google.common.base;\n" +
		"public class Preconditions {\n" +
		"    static public <T> T checkNotNull(T object) { return object; }\n" +
		"    static public <T> T checkNotNull(T object, Object message) { return object; }\n" +
		"    static public <T> T checkNotNull(T object, String message, Object... values) { return object; }\n" +
		"    static public void checkArgument(boolean expression) {}\n" +
		"    static public void checkArgument(boolean expression, Object message) {}\n" +
		"    static public void checkArgument(boolean expression, String msgTmpl, Object... messageArgs) {}\n" +
		"    static public void checkState(boolean expression) {}\n" +
		"    static public void checkState(boolean expression, Object message) {}\n" +
		"    static public void checkState(boolean expression, String msgTmpl, Object... messageArgs) {}\n" +
		"}\n";

public static Test suite() {
	return buildAllCompliancesTestSuite(testClass());
}

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

protected void setUp() throws Exception {
	super.setUp();
	if (this.assertLib == null) {
		String[] defaultLibs = getDefaultClassPaths();
		int len = defaultLibs.length;
		this.assertLib = new String[len+1];
		System.arraycopy(defaultLibs, 0, this.assertLib, 0, len);
		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.equinox.common"));
		if (bundleFile.isDirectory())
			this.assertLib[len] = bundleFile.getPath()+"/bin";
		else
			this.assertLib[len] = bundleFile.getPath();
	}
}

// Conditionally augment problem detection settings
static boolean setNullRelatedOptions = true;
protected Map getCompilerOptions() {
    Map defaultOptions = super.getCompilerOptions();
    if (setNullRelatedOptions) {
	    defaultOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
	    defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullReference, CompilerOptions.ERROR);
	    defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
		defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
		defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED);
    }
    return defaultOptions;
}

//https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575a() throws IOException {
		this.runConformTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    boolean b = o != null;\n" + // sheds doubts upon o
				"    org.eclipse.core.runtime.Assert.isLegal(o != null);\n" + 	// protection
				"    o.toString();\n" + 		// quiet
				"  }\n" +
				"}\n"},
			"",
			this.assertLib,
			true,
			null);
}

//https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575b() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(o == null);\n" + 	// forces null
				"    o.toString();\n" + 		// can only be null
				"  }\n" +
				"}\n"},
		"----------\n" +
		"1. ERROR in X.java (at line 4)\n" +
		"	o.toString();\n" +
		"	^\n" +
		"Null pointer access: The variable o can only be null at this location\n" +
		"----------\n",
		this.assertLib,
		true);
}

//https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575c() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o, boolean b) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(o != null || b, \"FAIL\");\n" + // shed doubts
				"    o.toString();\n" + 		// complain
				"  }\n" +
				"}\n"},
		"----------\n" +
		"1. ERROR in X.java (at line 4)\n" +
		"	o.toString();\n" +
		"	^\n" +
		"Potential null pointer access: The variable o may be null at this location\n" +
		"----------\n",
	    this.assertLib,
	    true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575d() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o1, Object o2) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(o1 != null && o2 == null);\n" +
				"    if (o1 == null) { };\n" + 		// complain
				"    if (o2 == null) { };\n" + 		// complain
				"  }\n" +
				"}\n"},
			"----------\n" + 
			"1. ERROR in X.java (at line 4)\n" + 
			"	if (o1 == null) { };\n" + 
			"	    ^^\n" + 
			"Null comparison always yields false: The variable o1 cannot be null at this location\n" + 
			"----------\n" + 
			"2. WARNING in X.java (at line 4)\n" + 
			"	if (o1 == null) { };\n" + 
			"	                ^^^\n" + 
			"Dead code\n" + 
			"----------\n" + 
			"3. ERROR in X.java (at line 5)\n" + 
			"	if (o2 == null) { };\n" + 
			"	    ^^\n" + 
			"Redundant null check: The variable o2 can only be null at this location\n" + 
			"----------\n",
		    this.assertLib,
		    true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575e() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(false && o != null);\n" +
				"    if (o == null) { };\n" + 		// quiet
				"  }\n" +
				"}\n"},
				"----------\n" + 
				"1. WARNING in X.java (at line 3)\n" + 
				"	org.eclipse.core.runtime.Assert.isLegal(false && o != null);\n" + 
				"	                                                 ^^^^^^^^^\n" + 
				"Dead code\n" + 
				"----------\n",
				this.assertLib, true);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575e_1() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"	 o = null;\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(false && o != null);\n" +
				"    if (o == null) { };\n" + 		// warn on o because o was null above.
				"  }\n" +
				"}\n"},
				"----------\n" + 
				"1. WARNING in X.java (at line 4)\n" + 
				"	org.eclipse.core.runtime.Assert.isLegal(false && o != null);\n" + 
				"	                                                 ^^^^^^^^^\n" + 
				"Dead code\n" + 
				"----------\n" + 
				"2. ERROR in X.java (at line 5)\n" + 
				"	if (o == null) { };\n" + 
				"	    ^\n" + 
				"Redundant null check: The variable o can only be null at this location\n" + 
				"----------\n",
				this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575e_2() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(true || o != null);\n" +
				"    if (o == null) { };\n" + 		// quiet
				"  }\n" +
				"}\n"},
				"----------\n" + 
				"1. WARNING in X.java (at line 3)\n" + 
				"	org.eclipse.core.runtime.Assert.isLegal(true || o != null);\n" + 
				"	                                                ^^^^^^^^^\n" + 
				"Dead code\n" + 
				"----------\n",
				this.assertLib, true);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
public void testBug127575f() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(false || o != null);\n" +
				"    if (o == null) { };\n" + 		// complain
				"  }\n" +
				"}\n"},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	if (o == null) { };\n" + 
		"	    ^\n" + 
		"Null comparison always yields false: The variable o cannot be null at this location\n" + 
		"----------\n" + 
		"2. WARNING in X.java (at line 4)\n" + 
		"	if (o == null) { };\n" + 
		"	               ^^^\n" + 
		"Dead code\n" + 
		"----------\n",
	    this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// do warn always false comparisons even inside org.eclipse.core.runtime.Assert.isLegal
public void testBug127575g() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo() {\n" +
				"    Object o = null;\n" +
				"    org.eclipse.core.runtime.Assert.isLegal(o != null);\n" +    // don't complain
				"    if (o == null) { };\n" +   // complain
				"  }\n" +
				"}\n"},
		"----------\n" + 
		"1. ERROR in X.java (at line 4)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal(o != null);\n" + 
		"	                                        ^\n" + 
		"Null comparison always yields false: The variable o can only be null at this location\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 5)\n" + 
		"	if (o == null) { };\n" + 
		"	    ^\n" + 
		"Null comparison always yields false: The variable o cannot be null at this location\n" + 
		"----------\n" + 
		"3. WARNING in X.java (at line 5)\n" + 
		"	if (o == null) { };\n" + 
		"	               ^^^\n" + 
		"Dead code\n" + 
		"----------\n",
		this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// Test to verify that asserts are exempted from redundant null check warnings,
// but this doesn't affect the downstream info.
public void testBug127575h() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void m() {\n" +
				"    X foo = new X();\n" +
				"	 org.eclipse.core.runtime.Assert.isLegal (foo != null);\n" +	// redundant check - don't warn
				"	 if (foo == null) {}\n" +
				"    X foo2 = new X();\n" +
				"	 org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" +	// always false check - warn
				"	 if (foo2 == null) {}\n" +
				"    X bar = null;\n" +
				"	 org.eclipse.core.runtime.Assert.isLegal (bar == null);\n" +	// redundant check - don't warn
				"	 if (bar == null) {}\n" +
				"    X bar2 = null;\n" +
				"	 org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" +	// always false check - warn
				"	 if (bar2 == null) {}\n" +
				"  }\n" +
				"}\n"},
		"----------\n" + 
		"1. ERROR in X.java (at line 5)\n" + 
		"	if (foo == null) {}\n" + 
		"	    ^^^\n" + 
		"Null comparison always yields false: The variable foo cannot be null at this location\n" + 
		"----------\n" + 
		"2. WARNING in X.java (at line 5)\n" + 
		"	if (foo == null) {}\n" + 
		"	                 ^^\n" + 
		"Dead code\n" + 
		"----------\n" + 
		"3. ERROR in X.java (at line 7)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable foo2 cannot be null at this location\n" + 
		"----------\n" + 
		"4. ERROR in X.java (at line 8)\n" + 
		"	if (foo2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Redundant null check: The variable foo2 can only be null at this location\n" + 
		"----------\n" + 
		"5. ERROR in X.java (at line 11)\n" + 
		"	if (bar == null) {}\n" + 
		"	    ^^^\n" + 
		"Redundant null check: The variable bar can only be null at this location\n" + 
		"----------\n" + 
		"6. ERROR in X.java (at line 13)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 can only be null at this location\n" + 
		"----------\n" + 
		"7. ERROR in X.java (at line 14)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 cannot be null at this location\n" + 
		"----------\n" + 
		"8. WARNING in X.java (at line 14)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	                  ^^\n" + 
		"Dead code\n" + 
		"----------\n",
	    this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// Test to verify that asserts are exempted from redundant null check warnings,
// but this doesn't affect the downstream info.
public void testBug127575i() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void m() {\n" +
				"	 X bar = null;\n" +
				"    X foo = getX();\n" +
				"    if (foo == null) {\n" +
				"	 	foo = new X();\n" +
				"	 }\n" +
				"	 org.eclipse.core.runtime.Assert.isTrue (foo != null && bar == null);\n" +	// don't warn but do the null analysis
				"	 if (foo != null) {}\n" +		// warn
				"	 if (bar == null) {}\n" +		// warn
				"  }\n" +
				"  public X getX() { return new X();}\n" +
				"}\n"},
		"----------\n" +
		"1. ERROR in X.java (at line 9)\n" + 
		"	if (foo != null) {}\n" + 
		"	    ^^^\n" + 
		"Redundant null check: The variable foo cannot be null at this location\n" + 
		"----------\n" + 
		"2. ERROR in X.java (at line 10)\n" + 
		"	if (bar == null) {}\n" + 
		"	    ^^^\n" + 
		"Redundant null check: The variable bar can only be null at this location\n" + 
		"----------\n",
	    this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// Test to verify that asserts are exempted from redundant null check warnings in a looping context,
// but this doesn't affect the downstream info.
public void testBug127575j() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void m() {\n" +
				"    X foo = new X();\n" +
				"    X foo2 = new X();\n" +
				"    X bar = null;\n" +
				"    X bar2 = null;\n" +
				"	 while (true) {\n" +
				"	 	org.eclipse.core.runtime.Assert.isLegal (foo != null);\n" +	//don't warn
				"	 	if (foo == null) {}\n" +
				"	 	org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" +	//don't warn
				"	 	if (foo2 == null) {}\n" +				
				"	 	org.eclipse.core.runtime.Assert.isLegal (bar == null);\n" +	//don't warn
				"	 	if (bar == null) {}\n" +				
				"	 	org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" +	//don't warn
				"	 	if (bar2 == null) {}\n" +
				"	 }\n" +
				"  }\n" +
				"}\n"},
		"----------\n" + 
		"1. ERROR in X.java (at line 9)\n" + 
		"	if (foo == null) {}\n" + 
		"	    ^^^\n" + 
		"Null comparison always yields false: The variable foo cannot be null at this location\n" + 
		"----------\n" + 
		"2. WARNING in X.java (at line 9)\n" + 
		"	if (foo == null) {}\n" + 
		"	                 ^^\n" + 
		"Dead code\n" + 
		"----------\n" + 
		"3. ERROR in X.java (at line 10)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable foo2 cannot be null at this location\n" + 
		"----------\n" + 
		"4. ERROR in X.java (at line 11)\n" + 
		"	if (foo2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Redundant null check: The variable foo2 can only be null at this location\n" + 
		"----------\n" + 
		"5. ERROR in X.java (at line 13)\n" + 
		"	if (bar == null) {}\n" + 
		"	    ^^^\n" + 
		"Redundant null check: The variable bar can only be null at this location\n" + 
		"----------\n" + 
		"6. ERROR in X.java (at line 14)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 can only be null at this location\n" + 
		"----------\n" + 
		"7. ERROR in X.java (at line 15)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 cannot be null at this location\n" + 
		"----------\n" + 
		"8. WARNING in X.java (at line 15)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	                  ^^\n" + 
		"Dead code\n" + 
		"----------\n",
	    this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// Test to verify that asserts are exempted from redundant null check warnings in a finally context,
// but this doesn't affect the downstream info.
public void testBug127575k() {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void m() {\n" +
				"    X foo = new X();\n" +
				"    X foo2 = new X();\n" +
				"    X bar = null;\n" +
				"    X bar2 = null;\n" +
				"	 try {\n" +
				"		System.out.println(\"Inside try\");\n" +
				"	 }\n" +
				"	 finally {\n" +
				"	 	org.eclipse.core.runtime.Assert.isLegal (foo != null);\n" +	//don't warn
				"	 	if (foo == null) {}\n" +
				"	 	org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" +	//don't warn
				"	 	if (foo2 == null) {}\n" +				
				"	 	org.eclipse.core.runtime.Assert.isLegal (bar == null);\n" +	//don't warn
				"	 	if (bar == null) {}\n" +				
				"	 	org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" +	//don't warn
				"	 	if (bar2 == null) {}\n" +
				"	 }\n" +
				"  }\n" +
				"}\n"},
		"----------\n" + 
		"1. ERROR in X.java (at line 12)\n" + 
		"	if (foo == null) {}\n" + 
		"	    ^^^\n" + 
		"Null comparison always yields false: The variable foo cannot be null at this location\n" + 
		"----------\n" + 
		"2. WARNING in X.java (at line 12)\n" + 
		"	if (foo == null) {}\n" + 
		"	                 ^^\n" + 
		"Dead code\n" + 
		"----------\n" + 
		"3. ERROR in X.java (at line 13)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (foo2 == null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable foo2 cannot be null at this location\n" + 
		"----------\n" + 
		"4. ERROR in X.java (at line 14)\n" + 
		"	if (foo2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Redundant null check: The variable foo2 can only be null at this location\n" + 
		"----------\n" + 
		"5. ERROR in X.java (at line 16)\n" + 
		"	if (bar == null) {}\n" + 
		"	    ^^^\n" + 
		"Redundant null check: The variable bar can only be null at this location\n" + 
		"----------\n" + 
		"6. ERROR in X.java (at line 17)\n" + 
		"	org.eclipse.core.runtime.Assert.isLegal (bar2 != null);\n" + 
		"	                                         ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 can only be null at this location\n" + 
		"----------\n" + 
		"7. ERROR in X.java (at line 18)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	    ^^^^\n" + 
		"Null comparison always yields false: The variable bar2 cannot be null at this location\n" + 
		"----------\n" + 
		"8. WARNING in X.java (at line 18)\n" + 
		"	if (bar2 == null) {}\n" + 
		"	                  ^^\n" + 
		"Dead code\n" + 
		"----------\n",
	    this.assertLib, true);
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// The condition of org.eclipse.core.runtime.Assert.isLegal is considered always true
// and alters the following analysis suitably.
public void testBug127575l() {
		this.runNegativeTest(
			new String[] {
				"Test.java",
				"public class Test {\n" +
				"	void foo(Object a, Object b, Object c) {\n" +
				"		org.eclipse.core.runtime.Assert.isLegal( a == null);\n " +
				"		if (a!=null) {\n" +
				"			System.out.println(\"a is not null\");\n" +
				"		 } else{\n" +
				"			System.out.println(\"a is null\");\n" +
				"		 }\n" +
				"		a = null;\n" +
				"		if (a== null) {}\n" +
				"		org.eclipse.core.runtime.Assert.isLegal(b != null);\n " +
				"		if (b!=null) {\n" +
				"			System.out.println(\"b is not null\");\n" +
				"		 } else{\n" +
				"			System.out.println(\"b is null\");\n" +
				"		 }\n" +
				"		org.eclipse.core.runtime.Assert.isLegal(c == null);\n" +
				"		if (c.equals(a)) {\n" +
				"			System.out.println(\"\");\n" +
				"		 } else{\n" +
				"			System.out.println(\"\");\n" +
				"		 }\n" +
				"	}\n" +
				"	public static void main(String[] args){\n" +
				"		Test test = new Test();\n" +
				"		test.foo(null,null, null);\n" +
				"	}\n" +
				"}\n"},
			"----------\n" + 
			"1. ERROR in Test.java (at line 4)\n" + 
			"	if (a!=null) {\n" + 
			"	    ^\n" + 
			"Null comparison always yields false: The variable a can only be null at this location\n" + 
			"----------\n" + 
			"2. WARNING in Test.java (at line 4)\n" + 
			"	if (a!=null) {\n" + 
			"			System.out.println(\"a is not null\");\n" + 
			"		 } else{\n" + 
			"	             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
			"Dead code\n" + 
			"----------\n" + 
			"3. ERROR in Test.java (at line 9)\n" + 
			"	a = null;\n" + 
			"	^\n" + 
			"Redundant assignment: The variable a can only be null at this location\n" + 
			"----------\n" + 
			"4. ERROR in Test.java (at line 10)\n" + 
			"	if (a== null) {}\n" + 
			"	    ^\n" + 
			"Redundant null check: The variable a can only be null at this location\n" + 
			"----------\n" + 
			"5. ERROR in Test.java (at line 12)\n" + 
			"	if (b!=null) {\n" + 
			"	    ^\n" + 
			"Redundant null check: The variable b cannot be null at this location\n" + 
			"----------\n" + 
			"6. WARNING in Test.java (at line 14)\n" + 
			"	} else{\n" + 
			"			System.out.println(\"b is null\");\n" + 
			"		 }\n" + 
			"	      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
			"Dead code\n" + 
			"----------\n" + 
			"7. ERROR in Test.java (at line 18)\n" + 
			"	if (c.equals(a)) {\n" + 
			"	    ^\n" + 
			"Null pointer access: The variable c can only be null at this location\n" + 
			"----------\n",
			this.assertLib, true);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// NPE warnings should be given inside org.eclipse.core.runtime.Assert.isLegal too
public void testBug127575m() {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				"Info.java",
				"public class Info {\n" +
				"	public void test(Info[] infos) {\n" +
				"		for (final Info info : infos) {\n " +
				"			if (info != null) {\n" +
				"				org.eclipse.core.runtime.Assert.isLegal( info.checkSomething());\n" +
				"		 		info.doSomething();\n" +	
				"			}\n" +
				"		 }\n" +
				"		for (final Info info : infos) {\n " +
				"			if (info == null) {\n" +
				"				org.eclipse.core.runtime.Assert.isLegal(info.checkSomething());\n" + // warn NPE
				"		 		info.doSomething();\n" +	
				"			}\n" +
				"		 }\n" +
				"	}\n" +
				"	void doSomething()  {}\n" +
				"	boolean checkSomething() {return true;}\n" +
				"}\n"},
				"----------\n" + 
			"1. ERROR in Info.java (at line 11)\n" + 
			"	org.eclipse.core.runtime.Assert.isLegal(info.checkSomething());\n" + 
			"	                                        ^^^^\n" + 
			"Null pointer access: The variable info can only be null at this location\n" + 
			"----------\n",
			this.assertLib,
			true);
	}
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// always false comparison in Assert.isLegal in loop should be warned against
public void testBug127575n() {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
		"DoWhileBug.java",
				"public class DoWhileBug {\n" + 
				"	void test(boolean b1) {\n" + 
				"		Object o1 = null;\n" + 
				"		Object o2 = null;\n" + 
				"		do {\n" +
				"           if (b1)\n" + 
				"				o1 = null;\n" +
				"           org.eclipse.core.runtime.Assert.isLegal (o1 != null);\n" +
				"		} while (true);\n" + 
				"	}\n" + 
				"}"	
			},
			"----------\n" + 
			"1. ERROR in DoWhileBug.java (at line 7)\n" + 
			"	o1 = null;\n" + 
			"	^^\n" + 
			"Redundant assignment: The variable o1 can only be null at this location\n" + 
			"----------\n" + 
			"2. ERROR in DoWhileBug.java (at line 8)\n" + 
			"	org.eclipse.core.runtime.Assert.isLegal (o1 != null);\n" + 
			"	                                         ^^\n" + 
			"Null comparison always yields false: The variable o1 can only be null at this location\n" + 
			"----------\n",
			this.assertLib,
			true);
	}
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127575
// "redundant null check" in Assert.isLegal in loop should not be warned against
public void testBug127575o() {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
		"DoWhileBug.java",
				"public class DoWhileBug {\n" + 
				"	void test(boolean b1) {\n" + 
				"		Object o1 = null;\n" + 
				"		Object o2 = null;\n" + 
				"		do {\n" +
				"           if (b1)\n" + 
				"				o1 = null;\n" +
				"           org.eclipse.core.runtime.Assert.isLegal ((o2 = o1) == null);\n" +
				"		} while (true);\n" + 
				"	}\n" + 
				"}"	
			},
			"----------\n" + 
			"1. ERROR in DoWhileBug.java (at line 7)\n" + 
			"	o1 = null;\n" + 
			"	^^\n" + 
			"Redundant assignment: The variable o1 can only be null at this location\n" + 
			"----------\n",
			this.assertLib,
			true);
	}
}

// https://bugs.eclipse.org/bugs/show_bug.cgi?id=373953
public void testBug373953() throws IOException {
		this.runNegativeTest(
			new String[] {
				"X.java",
				"public class X {\n" +
				"  void foo(Object o) {\n" +
				"    boolean b = o != null;\n" + // sheds doubts upon o
				"    java.eclipse.core.runtime.Assert.isLegal(o != null);\n" + 	// bogus Assert
				"    o.toString();\n" + 		// warn
				"  }\n" +
				"  void foo1(Object o) {\n" +
				"    boolean b = o != null;\n" + // sheds doubts upon o
				"    org.lang.core.runtime.Assert.isLegal(o != null);\n" + 	// bogus Assert
				"    o.toString();\n" + 		// warn
				"  }\n" +
				"}\n",
				"java.eclipse.core.runtime/Assert.java",
				"package java.eclipse.core.runtime;\n" +
				"public class Assert {\n" +
				"  public static void isLegal(boolean b) {\n" +
				"  }\n" +
				"}\n",
				"org.lang.core.runtime/Assert.java",
				"package org.lang.core.runtime;\n" +
				"public class Assert {\n" +
				"  public static void isLegal(boolean b) {\n" +
				"  }\n" +
				"}\n"},
			"----------\n" + 
			"1. ERROR in X.java (at line 5)\n" + 
			"	o.toString();\n" + 
			"	^\n" + 
			"Potential null pointer access: The variable o may be null at this location\n" + 
			"----------\n" + 
			"2. ERROR in X.java (at line 10)\n" + 
			"	o.toString();\n" + 
			"	^\n" + 
			"Potential null pointer access: The variable o may be null at this location\n" + 
			"----------\n");
}

// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// junit's assertNotNull
public void testBug382069a() throws IOException {
	this.runConformTest(
		new String[] {
			JUNIT_ASSERT_NAME,
			JUNIT_ASSERT_CONTENT,
			"X.java",
			"public class X {\n" +
			"  void foo(Object o1, String o2) {\n" +
			"    boolean b = o1 != null;\n" + // sheds doubts upon o1
			"    junit.framework.Assert.assertNotNull(o1);\n" + 	// protection
			"    o1.toString();\n" + 		// quiet
			"    b = o2 != null;\n" + // sheds doubts upon o2
			"    junit.framework.Assert.assertNotNull(\"msg\", o2);\n" + 	// protection
			"    o2.toString();\n" + 		// quiet
			"  }\n" +
			"}\n"},
		"");
}

// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// org.eclipse.core.runtime.Assert.isNotNull
public void testBug382069b() {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runConformTest(
			new String[] {
		"X.java",
				"public class X {\n" + 
				"  void foo(Object o1, String o2) {\n" +
				"    boolean b = o1 != null;\n" + // sheds doubts upon o1
				"    org.eclipse.core.runtime.Assert.isNotNull(o1);\n" + 	// protection
				"    o1.toString();\n" + 		// quiet
				"    b = o2 != null;\n" + // sheds doubts upon o2
				"    org.eclipse.core.runtime.Assert.isNotNull(o2, \"msg\");\n" + 	// protection
				"    o2.toString();\n" + 		// quiet
				"  }\n" +
				"}"	
			},
			"",
			this.assertLib,
			true,
			null);
	}
}

// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// junit's assertNull and dead code analysis
public void testBug382069c() throws IOException {
	this.runNegativeTest(
		new String[] {
			JUNIT_ASSERT_NAME,
			JUNIT_ASSERT_CONTENT,
			"X.java",
			"public class X {\n" +
			"  boolean foo(String o1, String o2) {\n" +
			"    junit.framework.Assert.assertNull(\"something's wrong\", o1);\n" + 	// establish nullness
			"    if (o2 == null)\n" +
			"        return o1 != null;\n" +
			"    junit.framework.Assert.assertNull(o2);\n" + // will always throw
			"    return false; // dead code\n" +
			"  }\n" +
			"  void bar(X x) {\n" +
			"    if (x == null) {\n" +
			"      junit.framework.Assert.assertNotNull(x);\n" +
			"      return; // dead code\n" +
			"    }\n" +
			"  }\n" +
			"}\n"},
			"----------\n" + 
			"1. ERROR in X.java (at line 5)\n" + 
			"	return o1 != null;\n" + 
			"	       ^^\n" + 
			"Null comparison always yields false: The variable o1 can only be null at this location\n" + 
			"----------\n" + 
			"2. WARNING in X.java (at line 7)\n" + 
			"	return false; // dead code\n" + 
			"	^^^^^^^^^^^^^\n" + 
			"Dead code\n" + 
			"----------\n" + 
			"3. WARNING in X.java (at line 12)\n" + 
			"	return; // dead code\n" + 
			"	^^^^^^^\n" + 
			"Dead code\n" + 
			"----------\n");
}
// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// various asserts from org.apache.commons.lang.Validate
public void testBug382069d() throws IOException {
	this.runNegativeTest(
		new String[] {
			APACHE_VALIDATE_NAME,
			APACHE_VALIDATE_CONTENT,
			"X.java",
			"import org.apache.commons.lang.Validate;\n" +
			"public class X {\n" +
			"  void foo(Object o1, String o2, X x) {\n" +
			"    boolean b = o1 != null;\n" + // sheds doubts upon o1
			"    Validate.notNull(o1);\n" + 	// protection
			"    o1.toString();\n" + 		// quiet
			"    b = o2 != null;\n" + // sheds doubts upon o2
			"    Validate.notNull(o2, \"msg\");\n" + 	// protection
			"    o2.toString();\n" + 		// quiet
			"    Validate.isTrue(x == null, \"ups\", x);\n" +
			"    x.foo(null, null, null); // definite NPE\n" +
			"  }\n" +
			"}\n"},
			"----------\n" + 
			"1. ERROR in X.java (at line 11)\n" + 
			"	x.foo(null, null, null); // definite NPE\n" + 
			"	^\n" + 
			"Null pointer access: The variable x can only be null at this location\n" + 
			"----------\n");
}
// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// various asserts from org.apache.commons.lang3Validate
public void testBug382069e() throws IOException {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				APACHE_3_VALIDATE_NAME,
				APACHE_3_VALIDATE_CONTENT,
				"X.java",
				"import org.apache.commons.lang3.Validate;\n" +
				"public class X {\n" +
				"  void foo(Object o1, String o2, X x) {\n" +
				"    boolean b = o1 != null;\n" + // sheds doubts upon o1
				"    Validate.notNull(o1);\n" + 	// protection
				"    o1.toString();\n" + 		// quiet
				"    b = o2 != null;\n" + // sheds doubts upon o2
				"    Validate.notNull(o2, \"msg\");\n" + 	// protection
				"    o2.toString();\n" + 		// quiet
				"    Validate.isTrue(x == null, \"ups\", x);\n" +
				"    x.foo(null, null, null); // definite NPE\n" +
				"  }\n" +
				"}\n"},
				"----------\n" + 
				"1. ERROR in X.java (at line 11)\n" + 
				"	x.foo(null, null, null); // definite NPE\n" + 
				"	^\n" + 
				"Null pointer access: The variable x can only be null at this location\n" + 
				"----------\n");
	}
}
// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// various asserts from com.google.common.base.Preconditions
public void testBug382069f() throws IOException {
	if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
		this.runNegativeTest(
			new String[] {
				GOOGLE_PRECONDITIONS_NAME,
				GOOGLE_PRECONDITIONS_CONTENT,
				"X.java",
				"import com.google.common.base.Preconditions;\n" +
				"public class X {\n" +
				"  void foo(Object o1, String o2, X x) {\n" +
				"    boolean b = o1 != null;\n" + // sheds doubts upon o1
				"    Preconditions.checkNotNull(o1);\n" + 	// protection
				"    o1.toString();\n" + 		// quiet
				"    b = o2 != null;\n" + // sheds doubts upon o2
				"    Preconditions.checkNotNull(o2, \"msg {0}.{1}\", o1, o2);\n" + 	// protection
				"    o2.toString();\n" + 		// quiet
				"    Preconditions.checkArgument(x == null, \"ups\");\n" +
				"    x.foo(null, null, null); // definite NPE\n" +
				"  }\n" +
				"}\n"},
				"----------\n" + 
				"1. ERROR in X.java (at line 11)\n" + 
				"	x.foo(null, null, null); // definite NPE\n" + 
				"	^\n" + 
				"Null pointer access: The variable x can only be null at this location\n" + 
				"----------\n");
	}
}
// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// java.util.Objects#requireNonNull
public void testBug382069g() throws IOException {
	if (this.complianceLevel >= ClassFileConstants.JDK1_7) {
		this.runConformTest(
			new String[] {
				"X.java",
				"import static java.util.Objects.requireNonNull;\n" +
				"public class X {\n" +
				"  void foo(Object o1, String o2, X x) {\n" +
				"    boolean b = o1 != null;\n" + // sheds doubts upon o1
				"    requireNonNull(o1);\n" + 	// protection
				"    o1.toString();\n" + 		// quiet
				"    b = o2 != null;\n" + // sheds doubts upon o2
				"    requireNonNull(o2, \"msg\");\n" + 	// protection
				"    o2.toString();\n" + 		// quiet
				"  }\n" +
				"}\n"},
				"");
	}
}

// https://bugs.eclipse.org/382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
// junit's assertTrue / assertFalse
public void testBug382069h() throws IOException {
	this.runConformTest(
		new String[] {
			JUNIT_ASSERT_NAME,
			JUNIT_ASSERT_CONTENT,
			"X.java",
			"public class X {\n" +
			"  void foo(Object o1, String o2) {\n" +
			"    boolean b = o1 != null;\n" + // sheds doubts upon o1
			"    junit.framework.Assert.assertTrue(o1 != null);\n" + 	// protection
			"    o1.toString();\n" + 		// quiet
			"    b = o2 != null;\n" + // sheds doubts upon o2
			"    junit.framework.Assert.assertFalse(\"msg\", o2 == null);\n" + 	// protection
			"    o2.toString();\n" + 		// quiet
			"  }\n" +
			"}\n"},
		"");
}
// Bug 401159 - [null] Respect org.junit.Assert for control flow
// various asserts from org.junit.Assert
public void testBug401159() throws IOException {
	this.runNegativeTest(
		new String[] {
			ORG_JUNIT_ASSERT_NAME,
			ORG_JUNIT_ASSERT_CONTENT,
			"X.java",
			"import org.junit.Assert;\n" +
			"public class X {\n" +
			"  void foo(Object o1, String o2, X x) {\n" +
			"    boolean b = o1 != null;\n" + // sheds doubts upon o1
			"    Assert.assertNotNull(o1);\n" + 	// protection
			"    o1.toString();\n" + 		// quiet
			"    b = o2 != null;\n" + // sheds doubts upon o2
			"    Assert.assertNotNull(\"msg\", o2);\n" + 	// protection
			"    o2.toString();\n" + 		// quiet
			"    Assert.assertTrue(\"ups\", x == null);\n" +
			"    x.foo(null, null, null); // definite NPE\n" +
			"  }\n" +
			"}\n"},
			"----------\n" + 
			"1. ERROR in X.java (at line 11)\n" + 
			"	x.foo(null, null, null); // definite NPE\n" + 
			"	^\n" + 
			"Null pointer access: The variable x can only be null at this location\n" + 
			"----------\n");
}

// https://bugs.eclipse.org/472618 - [compiler][null] assertNotNull vs. Assert.assertNotNull
// junit's assertNotNull
public void testBug472618() throws IOException {
	if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses auto-unboxing
	this.runConformTest(
		new String[] {
			JUNIT_ASSERT_NAME,
			JUNIT_ASSERT_CONTENT,
			"AssertionTest.java",
			"import junit.framework.Assert;\n" + 
			"\n" + 
			"public class AssertionTest extends Assert\n" + 
			"{\n" + 
			"    void test()\n" + 
			"    {\n" + 
			"        Long test = null;\n" + 
			"\n" + 
			"        if(Boolean.TRUE)\n" + 
			"        {\n" + 
			"            test = 0L;\n" + 
			"        }\n" + 
			"\n" + 
			"        assertNotNull(test);\n" + 
			"\n" + 
			"        test.longValue();  // <- potential null pointer access\n" + 
			"    }\n" + 
			"}\n"},
		"");
}
}
