package org.eclipse.debug.jdi.tests;

/**********************************************************************
Copyright (c) 2000, 2002 IBM Corp.  All rights reserved.
This file is made available under the terms of the Common Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/cpl-v10.html
**********************************************************************/

import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import junit.framework.Test;

import com.sun.jdi.BooleanValue;
import com.sun.jdi.ByteValue;
import com.sun.jdi.CharValue;
import com.sun.jdi.DoubleValue;
import com.sun.jdi.FloatValue;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.LongValue;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ShortValue;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.ThreadReference;

/**
 * Tests for JDI com.sun.jdi.VirtualMachine
 * and JDWP VM command set.
 * 
 * Example of arguments:
 *   -launcher SunVMLauncher -address c:\jdk1.2.2\ -classpath d:\target
 */
public class VirtualMachineTest extends AbstractJDITest {

	/**
	 * Creates a new test .
	 */
	public VirtualMachineTest() {
		super();
	}
	/**
	 * Init the fields that are used by this test only.
	 */
	public void localSetUp() {
	}
	/**
	 * Run all tests and output to standard output.
	 */
	public static void main(java.lang.String[] args) {
		new VirtualMachineTest().runSuite(args);
	}
	/**
	 * Gets the name of the test case.
	 */
	public String getName() {
		return "com.sun.jdi.VirtualMachine";
	}
	/**
	 * Don't start the program yet, so that the testNotStarted* tests can run before.
	 */
	protected void setUp() {
		launchTargetAndConnectToVM();
	}
	/**
	 * Starts the target program.
	 * NB: This method is copied in this class only so that it can be invoked
	 *     dynamically.
	 */
	public void startProgram() {
		super.startProgram();
	}
	/**
	 * Returns all tests 
	 */
	protected Test suite() {
		JDITestSuite suite = new JDITestSuite(this);

		// Tests that run before the program is started
		Vector testNames = getAllMatchingTests("testNotStarted");
		Iterator iterator = testNames.iterator();
		while (iterator.hasNext()) {
			String name = (String) iterator.next();
			suite.addTest(new JDITestCase(this, name));
		}

		// The method that starts the program
		suite.addTest(new JDITestCase(this, "startProgram"));

		// Tests that run after the program has started
		testNames = getAllMatchingTests("testStarted");
		iterator = testNames.iterator();
		while (iterator.hasNext()) {
			String name = (String) iterator.next();
			suite.addTest(new JDITestCase(this, name));
		}

		// All other tests
		testNames = getAllMatchingTests("testJDI");
		iterator = testNames.iterator();
		while (iterator.hasNext()) {
			String name = (String) iterator.next();
			suite.addTest(new JDITestCase(this, name));
		}

		return suite;
	}
	/**
	 * Test JDI canGetBytecodes().
	 */
	public void testJDICanGetBytecodes() {
		fVM.canGetBytecodes();
	}
	/**
	 * Test JDI canGetCurrentContendedMonitor().
	 */
	public void testJDICanGetCurrentContendedMonitor() {
		fVM.canGetCurrentContendedMonitor();
	}
	/**
	 * Test JDI canGetMonitorInfo().
	 */
	public void testJDICanGetMonitorInfo() {
		fVM.canGetMonitorInfo();
	}
	/**
	 * Test JDI canGetOwnedMonitorInfo().
	 */
	public void testJDICanGetOwnedMonitorInfo() {
		fVM.canGetOwnedMonitorInfo();
	}
	/**
	 * Test JDI canGetSyntheticAttribute().
	 */
	public void testJDICanGetSyntheticAttribute() {
		//  This is optional functionality, thus this is not a failure
		fVM.canGetSyntheticAttribute();
	}
	/**
	 * Test JDI canWatchFieldAccess().
	 */
	public void testJDICanWatchFieldAccess() {
		//  This is optional functionality, thus this is not a failure
		fVM.canWatchFieldAccess();
	}
	/**
	 * Test JDI canWatchFieldModification().
	 */
	public void testJDICanWatchFieldModification() {
		//  This is optional functionality, thus this is not a failure
		fVM.canWatchFieldModification();
	}
	/**
	 * Test JDI eventQueue().
	 */
	public void testJDIEventQueue() {
		assertNotNull("1", fVM.eventQueue());
	}
	/**
	 * Test JDI eventRequestManager().
	 */
	public void testJDIEventRequestManager() {
		assertNotNull("1", fVM.eventRequestManager());
	}
	/**
	 * Test JDI mirrorOf(boolean).
	 */
	public void testJDIMirrorOfBoolean() {
		boolean value = true;
		BooleanValue mirror = fVM.mirrorOf(value);
		assertTrue("1", value == mirror.value());
	}
	/**
	 * Test JDI mirrorOf(byte).
	 */
	public void testJDIMirrorOfByte() {
		byte value = 1;
		ByteValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value());
	}
	/**
	 * Test JDI mirrorOf(char).
	 */
	public void testJDIMirrorOfChar() {
		char value = 'a';
		CharValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value());
	}
	/**
	 * Test JDI mirrorOf(double).
	 */
	public void testJDIMirrorOfDouble() {
		double value = 12345.6789;
		DoubleValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value(), 0);
	}
	/**
	 * Test JDI mirrorOf(float).
	 */
	public void testJDIMirrorOfFloat() {
		float value = 12345.6789f;
		FloatValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value(), 0);
	}
	/**
	 * Test JDI mirrorOf(int).
	 */
	public void testJDIMirrorOfInt() {
		int value = 12345;
		IntegerValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value());
	}
	/**
	 * Test JDI mirrorOf(long).
	 */
	public void testJDIMirrorOfLong() {
		long value = 1234567890l;
		LongValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value());
	}
	/**
	 * Test JDI mirrorOf(short).
	 */
	public void testJDIMirrorOfShort() {
		short value = (short) 12345;
		ShortValue mirror = fVM.mirrorOf(value);
		assertEquals("1", value, mirror.value());
	}
	/**
	 * Test JDI mirrorOf(String) and JDWP 'VM - Create String'.
	 */
	public void testJDIMirrorOfString() {
		String testString = "Test";
		StringReference newString = null;
		newString = fVM.mirrorOf(testString);
		assertEquals("1", newString.value(), testString);
	}
	/**
	 * Test JDI setDebugTraceMode(int).
	 */
	public void testJDISetDebugTraceMode() {
		fVM.setDebugTraceMode(com.sun.jdi.VirtualMachine.TRACE_ALL);
		fVM.setDebugTraceMode(com.sun.jdi.VirtualMachine.TRACE_SENDS);
		fVM.setDebugTraceMode(com.sun.jdi.VirtualMachine.TRACE_RECEIVES);
		fVM.setDebugTraceMode(com.sun.jdi.VirtualMachine.TRACE_NONE);

		// restore original value
		fVM.setDebugTraceMode(fVMTraceFlags);
	}
	/**
	 * Test JDI getVersion().
	 */
	public void testJDIVersion() {
		String version = fVM.version();
		assertTrue("1", version != null);
	}
	/**
	 * Test JDI allClasses() and JDWP 'VM - Get all classes'
	 * while the test program has not been started.
	 */
	public void testNotStartedAllClasses() {
		List classes = fVM.allClasses();
		Iterator iterator = classes.listIterator();
		int i = 0;
		while (iterator.hasNext())
			assertTrue(Integer.toString(i++), iterator.next() instanceof ReferenceType);
	}
	/**
	 * Test JDI allThreads() and JDWP 'VM - Get all threads'
	 * while the test program has not been started.
	 */
	public void testNotStartedAllThreads() {
		List threads = fVM.allThreads();
		Iterator iterator = threads.listIterator();
		int i = 0;
		while (iterator.hasNext())
			assertTrue(Integer.toString(i++), iterator.next() instanceof ThreadReference);
	}
	/**
	 * Test JDI classesByName() while the test program has not been started.
	 */
	public void testNotStartedClassesByName() {
		List classes = fVM.classesByName("java.lang.Object");
		assertEquals("1", 1, classes.size());
	}
	/**
	 * Test JDI allClasses() and JDWP 'VM- Get all classes'
	 * once the test program has been started.
	 */
	public void testStartedAllClasses() {

		// The test program has started, the number of classes is != 0
		List classes = fVM.allClasses();
		assertTrue("1", classes.size() != 0);

		// Collect names of received classes
		String[] names = new String[classes.size()];
		ListIterator iterator = classes.listIterator();
		int i = 0;
		while (iterator.hasNext()) {
			ReferenceType type = (ReferenceType) iterator.next();
			names[i++] = type.name();
		}

		// Check that they are the expected names
		String[] expected =
			new String[] {
				"java.lang.Object",
				"java.util.Date",
				"org.eclipse.debug.jdi.tests.program.Printable",
				"org.eclipse.debug.jdi.tests.program.MainClass" };
		for (int j = 0; j < expected.length; j++) {
			boolean isIncluded = false;
			iteration : for (int k = 0; k < names.length; k++) {
				if (names[k].equals(expected[j])) {
					isIncluded = true;
					break iteration;
				}
			}
			assertTrue("2." + j, isIncluded);
		}
	}
	/**
	 * Test JDI allThreads() and JDWP 'VM - Get all threads'
	 * once the test program has been started.
	 */
	public void testStartedAllThreads() {

		// The test program has started, the number of threads is != 0
		List threads = fVM.allThreads();
		assertTrue("1", threads.size() != 0);

		// Collect names of received threads
		String[] names = new String[threads.size()];
		ListIterator iterator = threads.listIterator();
		int i = 0;
		while (iterator.hasNext()) {
			ThreadReference thread = (ThreadReference) iterator.next();
			names[i++] = thread.name();
		}

		// Check that they contain at least the expected names
		String[] expected = new String[] { "Test Thread" };
		boolean isIncluded = false;
		iteration : for (int j = 0; j < expected.length; j++) {
			for (int k = 0; k < names.length; k++) {
				if (expected[j].equals(names[k])) {
					isIncluded = true;
					break iteration;
				}
			}
		}
		assertTrue("2", isIncluded);
	}
	/**
	 * Test JDI classesByName() once the test program has been started.
	 */
	public void testStartedClassesByName() {

		// The test program has started, the number of java.lang.Object is 1
		List classes = fVM.classesByName("java.lang.Object");
		assertEquals("1", classes.size(), 1);

		// Collect names of received classes
		String[] names = new String[classes.size()];
		ListIterator iterator = classes.listIterator();
		int i = 0;
		while (iterator.hasNext()) {
			ReferenceType type = (ReferenceType) iterator.next();
			names[i++] = type.name();
		}

		// Check that they are all "java.lang.Object"
		for (int j = 0; j < names.length; j++) {
			assertEquals("2." + j, "java.lang.Object", names[j]);
		}
	}
	/**
	 * Test JDI suspend() and resume() once the test program has been started.
	 */
	public void testStartedSuspendResume() {
		// Suspend
		fVM.suspend();
		ListIterator threads = fVM.allThreads().listIterator();
		while (threads.hasNext()) {
			ThreadReference thread = (ThreadReference) threads.next();
			assertTrue("1." + thread.name(), thread.isSuspended());
		}

		// Resume
		fVM.resume();
		// Cannot assertTrue that all threads are not suspended because they might have been suspended
		// by the program itself

		// Suspend VM and suspend one thread
		fVM.suspend();
		threads = fVM.allThreads().listIterator();
		ThreadReference suspended = getThread();
		suspended.suspend();
		while (threads.hasNext()) {
			ThreadReference thread = (ThreadReference) threads.next();
			assertTrue("2." + thread.name(), thread.isSuspended());
		}

		// Resume VM and ensure that the one thread that was suspended is still suspended
		fVM.resume();
		assertTrue("3", suspended.isSuspended());
	}
	/**
	 * Test JDI topLevelThreadGroups().
	 */
	public void testStartedTopLevelThreadGroups() {
		List topLevelThreadGroups = fVM.topLevelThreadGroups();
		assertEquals("1", 1, topLevelThreadGroups.size());
		assertTrue("2", topLevelThreadGroups.get(0) instanceof ThreadGroupReference);
	}
}