/*******************************************************************************
 * Copyright (c) 2000, 2015 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.debug.jdi.tests;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import com.sun.jdi.Field;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;

/**
 * Tests for JDI com.sun.jdi.ReferenceType
 * and JDWP Type command set.
 */
public class ReferenceTypeTest extends AbstractJDITest {

	private List<ReferenceType> fTypes = new LinkedList<>();

	// These must match what is done in localSetUp
	private boolean[] fSystemClassLoader = { true, true, false, false };
	private boolean[] fHasMethods = { true, false, true, true };
	private boolean[] fIsAbstract = { false, false, false, true };
	private boolean[] fIsFinal = { false, true, false, false };
	private boolean[] fIsStatic = { false, false, false, false };
	private String[] fTypeName =
		{
			"java.lang.Object",
			"java.lang.String[]",
			"org.eclipse.debug.jdi.tests.program.MainClass",
			"org.eclipse.debug.jdi.tests.program.Printable" };
	private int fObjectIndex = 0;
	private int fMainClassIndex = 2;

	/**
	 * Creates a new test.
	 */
	public ReferenceTypeTest() {
		super();
	}
	/**
	 * Init the fields that are used by this test only.
	 */
	@Override
	public void localSetUp() {
		// Get all kinds of reference type
		fTypes.add(getSystemType());
		fTypes.add(getArrayType());
		fTypes.add(getMainClass());
		fTypes.add(getInterfaceType());
	}
	/**
	 * Run all tests and output to standard output.
	 * @param args
	 */
	public static void main(java.lang.String[] args) {
		new ReferenceTypeTest().runSuite(args);
	}
	/**
	 * Gets the name of the test case.
	 * @see junit.framework.TestCase#getName()
	 */
	@Override
	public String getName() {
		return "com.sun.jdi.ReferenceType";
	}
	/**
	 * Test JDI allFields().
	 */
	public void testJDIAllFields() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			Iterator<?> all = type.allFields().iterator();
			int i = 0;
			while (all.hasNext())
				assertTrue("1." + type.name() + "." + i++, all.next() instanceof Field);
		}
	}
	/**
	 * Test JDI allMethods().
	 */
	public void testJDIAllMethods() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			Iterator<?> all = type.allMethods().iterator();
			int i = 0;
			while (all.hasNext())
				assertTrue("1." + type.name() + "." + i++, all.next() instanceof Method);
		}
	}
	/**
	 * Test JDI classLoader() and JDWP 'Type - Get class loader'.
	 */
	public void testJDIClassLoader() {
		for (int i = 0; i < fTypes.size(); ++i) {
			ReferenceType type = fTypes.get(i);
			ObjectReference classLoader = type.classLoader();
			assertTrue("1." + i, (classLoader == null) == fSystemClassLoader[i]);
		}
	}
	/**
	 * Test JDI classObject().
	 */
	public void testJDIClassObject() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue(type.name(), type.classObject() != null);
		}
	}
	/**
	 * Test JDI equals() and hashCode().
	 */
	public void testJDIEquality() {
		ReferenceType other =
			fVM.classesByName("java.lang.String").get(0);
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue("1." + type.name() + ".1", type.equals(type));
			assertTrue("1." + type.name() + ".2", !type.equals(other));
			assertTrue("1." + type.name() + ".3", !type.equals(fVM));
			assertTrue("1." + type.name() + ".4", !type.equals(new Object()));
			assertTrue("1." + type.name() + ".5", !type.equals(null));
			assertTrue("1." + type.name() + ".6", type.hashCode() != other.hashCode());
		}
	}
	/**
	 * Test JDI failedToInitialize().
	 */
	public void testJDIFailedToInitialize() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue("1." + type.name(), !type.failedToInitialize());
		}
	}
	/**
	 * Test JDI fieldByName(String).
	 */
	public void testJDIFieldByName() {
		// NB: This tests the class type only, it should test the others too
		ReferenceType type = fTypes.get(fMainClassIndex);
		Field field = type.fieldByName("fObject");
		assertTrue("1." + type.name(), field != null);
	}
	/**
	 * Test JDI fields() and JDWP 'Type - Get Fields'.
	 */
	public void testJDIFields() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			Iterator<?> fields = type.fields().iterator();
			int i = 0;
			while (fields.hasNext())
				assertTrue("1." + i++ +"." + type.name(), fields.next() instanceof Field);
		}
	}
	/**
	 * Test JDI getValue(Field) and JDWP 'Type - Get Fields Values'.
	 */
	public void testJDIGetValue() {
		// NB: This tests the class type only, it should test the others too
		ReferenceType type = fTypes.get(fMainClassIndex);
		Field field = type.fieldByName("fInt");
		assertTrue("1." + type.name(), field != null);
		assertTrue("2." + type.name(), type.getValue(field) instanceof IntegerValue);
	}
	/**
	 * Test JDI getValues(List) and JDWP 'Type - Get Fields Values'.
	 */
	public void testJDIGetValues() {
		// NB: This tests the class type only, it should test the others too
		ReferenceType type = fTypes.get(fMainClassIndex);

		// Get field values
		List<?> fields = type.fields();
		ListIterator<?> iterator = fields.listIterator();
		List<Field> staticFields = new LinkedList<>();
		while (iterator.hasNext()) {
			Field field = (Field) iterator.next();
			if (field.isStatic())
				staticFields.add(field);
		}
		Map<?, ?> values = type.getValues(staticFields);
		assertEquals("1." + type.name(), 24, values.size());

		// Get value of field fInt in MainClass
		Field field = staticFields.get(0);
		int i = 0;
		while (!field.name().equals("fInt"))
			field = staticFields.get(++i);

		// Ensure it is an integer value
		assertTrue("2." + type.name(), values.get(field) instanceof IntegerValue);
	}
	/**
	 * Test JDI isAbstract().
	 */
	public void testJDIIsAbstract() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			if (type.name().equals("org.eclipse.debug.jdi.tests.program.Printable"))
				assertTrue("1." + type.name(), type.isAbstract());
			else
				assertTrue("2." + type.name(), !type.isAbstract());
		}
	}
	/**
	 * Test JDI isFinal().
	 */
	public void testJDIIsFinal() {
		for (int i = 0; i < fTypes.size(); ++i) {
			ReferenceType type = fTypes.get(i);
			assertTrue("1." + i, type.isFinal() == fIsFinal[i]);
		}
	}
	/**
	 * Test JDI isInitialized().
	 */
	public void testJDIIsInitialized() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue("1." + type.name(), type.isInitialized());
		}
	}
	/**
	 * Test JDI isPrepared().
	 */
	public void testJDIIsPrepared() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue("1." + type.name(), type.isPrepared());
		}
	}
	/**
	 * Test JDI isStatic().
	 */
	public void testJDIIsStatic() {
		ListIterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			assertTrue("1." + type.name(), !type.isStatic());
		}
	}
	/**
	 * Test JDI isVerified().
	 */
	public void testJDIIsVerified() {
		for (int i = 0; i < fTypes.size(); ++i) {
			if (i != fObjectIndex) {
				ReferenceType type = fTypes.get(i);
				assertTrue("1." + type.name(), type.isVerified());
			}
		}
	}
	/**
	 * Test JDI methods() and JDWP 'Type - Get Methods'.
	 */
	public void testJDIMethods() {
		for (int i = 0; i < fTypes.size(); ++i) {
			ReferenceType type = fTypes.get(i);
			List<?> methods = type.methods();
			assertTrue("" + i, (methods.size() != 0) == fHasMethods[i]);
		}
	}
	/**
	 * Test JDI methodsByName(String) and methodsByName(String, String).
	 */
	public void testJDIMethodsByName() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();

			// methodsByName(String)
			Iterator<?> methods = type.methodsByName("run").iterator();
			while (methods.hasNext())
				assertTrue("1." + type.name(), methods.next() instanceof Method);
			assertEquals("2", 0, type.methodsByName("fraz").size());

			// methodsByName(String, String)
			methods = type.methodsByName("run", "()V").iterator();
			while (methods.hasNext())
				assertTrue("3." + type.name(), methods.next() instanceof Method);
			assertEquals("4", 0, type.methodsByName("fraz", "()Z").size());
		}
	}
	/**
	 * Test JDI isAbstract(), isFinal() and isStatic()
	 * and JDWP 'Type - Get modifiers'.
	 */
	public void testJDIModifiers() {
		for (int i = 0; i < fTypes.size(); ++i) {
			ReferenceType type = fTypes.get(i);
			if (i != 2) {
				// i == 2 corresponds to an ArrayType, isAbstract() is undefined
				assertTrue("1." + i, type.isAbstract() == fIsAbstract[i]);
			}
			assertTrue("2." + i, type.isFinal() == fIsFinal[i]);
			assertTrue("3." + i, type.isStatic() == fIsStatic[i]);
		}
	}
	/**
	 * Test JDI name() and JDWP 'Type - Get signature'.
	 */
	public void testJDIName() {
		for (int i = 0; i < fTypes.size(); ++i) {
			ReferenceType type = fTypes.get(i);
			assertEquals("" + i, type.name(), fTypeName[i]);
		}
	}
	/**
	 * Test JDI nestedTypes().
	 */
	public void testJDINestedTypes() {
		// NB: This tests the class type only, it should test the others too
		ReferenceType type = getClass("org.eclipse.debug.jdi.tests.program.OtherClass");
		assertTrue("1." + type.name(), type != null);
		List<?> nestedTypes = type.nestedTypes();
		assertEquals("2." + type.name(), 1, nestedTypes.size());
		assertTrue("3." + type.name(), nestedTypes.get(0) instanceof ReferenceType);
	}
	/**
	 * Test JDI visibleFields().
	 */
	public void testJDIVisibleFields() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			List<?> all = type.allFields();
			Iterator<?> visible = type.visibleFields().iterator();
			while (visible.hasNext()) {
				Field next = (Field) visible.next();
				assertTrue("1." + type.name() + "." + next.name(), all.contains(next));
			}
		}
	}
	/**
	 * Test JDI visibleMethods().
	 */
	public void testJDIVisibleMethods() {
		Iterator<ReferenceType> iterator = fTypes.listIterator();
		while (iterator.hasNext()) {
			ReferenceType type = iterator.next();
			List<?> all = type.allMethods();
			Iterator<?> visible = type.visibleMethods().iterator();
			while (visible.hasNext()) {
				Method next = (Method) visible.next();
				assertTrue("1." + type.name() + "." + next.name(), all.contains(next));
			}
		}
	}
}
