/*******************************************************************************
 * Copyright (c) 2004, 2012 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 org.eclipse.jdi.internal.StringReferenceImpl;

import com.sun.jdi.Method;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.event.BreakpointEvent;
import com.sun.jdi.event.MethodExitEvent;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.MethodExitRequest;

/**
 * Test cases for method exit event return values in java 1.6 VM
 * 
 * @since 3.3
 */
public class MethodReturnValuesTests extends AbstractJDITest {
	
	MethodExitRequest req = null;
	Value val = null;
	MethodExitEvent event = null;
	EventRequestManager erm = null;
	Method method = null;
	BreakpointRequest br = null;
	EventWaiter waiter = null;
	BreakpointEvent bpe = null;
	ThreadReference tref = null;
	
	
	/** setup test info locally **/
	@Override
	public void localSetUp() {
		erm = fVM.eventRequestManager();
	}
	
	/** cleans up local tests **/
	@Override
	public void localTearDown() {
		super.localTearDown();
		if(erm != null) {
			erm.deleteAllBreakpoints();
		}
	}
	
	/**
	 * test to make sure 1.6 VM supports method return values 
	 */
	public void testCanGetMethodReturnValues() {
		if(is16OrGreater()) {
			assertTrue("Should have method return values capabilities", fVM.canGetMethodReturnValues());
		}
		else {
			assertFalse("Should not have method return values capabilities", fVM.canGetMethodReturnValues());
		}
	}
	
	/**
	 * test getting a void return value.
	 * not applicable to non 1.6 VMs
	 */
	public void testGetVoidMethodReturnValue() {
		if(!fVM.canGetMethodReturnValues()) {
			return;
		}
		try {
			//test VoidValueImpl return type
			method = getMethod("print", "(Ljava/io/OutputStream;)V");
			br = getBreakpointRequest(method.location());
			br.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			br.enable();
			waiter = new EventWaiter(br, true);
			fEventReader.addEventListener(waiter);
			triggerEvent("forcereturn");
			bpe = (BreakpointEvent) waiter.waitEvent(5000);
			tref = bpe.thread();
			fEventReader.removeEventListener(waiter);
			if(tref.isSuspended()) {
				req = erm.createMethodExitRequest();
				req.addClassFilter("org.eclipse.debug.jdi.tests.program.*");
				req.enable();
				waiter = new EventWaiter(req, true);
				fEventReader.addEventListener(waiter);
				tref.resume();
				event = (MethodExitEvent)waiter.waitEvent(10000);
				fEventReader.removeEventListener(waiter);
				assertNotNull("event should not be null", event);
				assertEquals(req, event.request());
				val = event.returnValue();
				assertNotNull("value should not be null", val);
				assertTrue("return value must be void", val.equals(val.virtualMachine().mirrorOfVoid()));
				erm.deleteEventRequest(req);
			}
		}
		catch (InterruptedException e) {
			assertTrue("thrown exception mean failure", false);
		}
	}
	
	/**
	 * test to make sure that returnValue is working to spec.
	 * test is not applicable to non 1.6 VMs
	 */
	public void testGetStringMethodReturnValue() {
		if(!fVM.canGetMethodReturnValues()) {
			return;
		}
		try {
			//test non void return types, in the case IntegerValueImpl
			method = getMethod("foo", "()Ljava/lang/String;");
			br = getBreakpointRequest(method.location());
			br.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			br.enable();
			waiter = new EventWaiter(br, true);
			fEventReader.addEventListener(waiter);
			triggerEvent("fooreturn");
			bpe = (BreakpointEvent) waiter.waitEvent(5000);
			fEventReader.removeEventListener(waiter);
			tref = bpe.thread();
			if(tref.isSuspended()) {
				req = erm.createMethodExitRequest();
				req.addClassFilter("org.eclipse.debug.jdi.tests.program.*");
				req.enable();
				waiter = new EventWaiter(req, true);
				fEventReader.addEventListener(waiter);
				tref.resume();
				event = (MethodExitEvent)waiter.waitEvent(5000);
				fEventReader.removeEventListener(waiter);
				assertNotNull("event should not be null", event);
				assertEquals(req, event.request());
				val = event.returnValue();
				assertNotNull("value should not be null", val);
				assertTrue("return value must be StringReferenceImpl", val instanceof StringReferenceImpl);
				erm.deleteEventRequest(req);
			}
		} 
		catch (InterruptedException e) {
			assertTrue("thrown exception mean failure", false);
		}
	}
	
	/**
	 * test to make sure that returnValue is working to spec.
	 * test is not applicable to non 1.6 VMs
	 */
	public void testGetIntMethodReturnValue() {
		if(!fVM.canGetMethodReturnValues()) {
			return;
		}
		try {
			//test non void return types, in the case IntegerValueImpl
			method = getMethod("getInt", "()I");
			br = getBreakpointRequest(method.location());
			br.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			br.enable();
			waiter = new EventWaiter(br, true);
			fEventReader.addEventListener(waiter);
			triggerEvent("getInt");
			bpe = (BreakpointEvent) waiter.waitEvent(5000);
			fEventReader.removeEventListener(waiter);
			tref = bpe.thread();
			if(tref.isSuspended()) {
				req = erm.createMethodExitRequest();
				req.addClassFilter("org.eclipse.debug.jdi.tests.program.*");
				req.enable();
				waiter = new EventWaiter(req, true);
				fEventReader.addEventListener(waiter);
				tref.resume();
				event = (MethodExitEvent)waiter.waitEvent(5000);
				fEventReader.removeEventListener(waiter);
				assertNotNull("event should not be null", event);
				assertEquals(req, event.request());
				val = event.returnValue();
				assertNotNull("value should not be null", val);
				assertEquals("return value must be 20", val.virtualMachine().mirrorOf(20), val);
				erm.deleteEventRequest(req);
			}
		} 
		catch (InterruptedException e) {
			assertTrue("thrown exception mean failure", false);
		}
	}	
	
	/**
	 * test to make sure that returnValue is working to spec.
	 * test is not applicable to non 1.6 VMs
	 */
	public void testGetBooleanMethodReturnValue() {
		if(!fVM.canGetMethodReturnValues()) {
			return;
		}
		try {
			//test non void return types, in the case IntegerValueImpl
			method = getMethod("getBoolean", "()Z");
			br = getBreakpointRequest(method.location());
			br.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			br.enable();
			waiter = new EventWaiter(br, true);
			fEventReader.addEventListener(waiter);
			triggerEvent("getBoolean");
			bpe = (BreakpointEvent) waiter.waitEvent(5000);
			fEventReader.removeEventListener(waiter);
			tref = bpe.thread();
			if(tref.isSuspended()) {
				req = erm.createMethodExitRequest();
				req.addClassFilter("org.eclipse.debug.jdi.tests.program.*");
				req.enable();
				waiter = new EventWaiter(req, true);
				fEventReader.addEventListener(waiter);
				tref.resume();
				event = (MethodExitEvent)waiter.waitEvent(5000);
				fEventReader.removeEventListener(waiter);
				assertNotNull("event should not be null", event);
				assertEquals(req, event.request());
				val = event.returnValue();
				assertNotNull("value should not be null", val);
				assertEquals("return value must be true", val.virtualMachine().mirrorOf(true), val);
				erm.deleteEventRequest(req);
			}
		} 
		catch (InterruptedException e) {
			assertTrue("thrown exception mean failure", false);
		}
	}		
	
	/**
	 * test to make sure that returnValue is working to spec.
	 * test is not applicable to non 1.6 VMs
	 */
	public void testGetLongMethodReturnValue() {
		if(!fVM.canGetMethodReturnValues()) {
			return;
		}
		try {
			//test non void return types, in the case IntegerValueImpl
			method = getMethod("getLong", "()J");
			br = getBreakpointRequest(method.location());
			br.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			br.enable();
			waiter = new EventWaiter(br, true);
			fEventReader.addEventListener(waiter);
			triggerEvent("getLong");
			bpe = (BreakpointEvent) waiter.waitEvent(5000);
			fEventReader.removeEventListener(waiter);
			tref = bpe.thread();
			if(tref.isSuspended()) {
				req = erm.createMethodExitRequest();
				req.addClassFilter("org.eclipse.debug.jdi.tests.program.*");
				req.enable();
				waiter = new EventWaiter(req, true);
				fEventReader.addEventListener(waiter);
				tref.resume();
				event = (MethodExitEvent)waiter.waitEvent(5000);
				fEventReader.removeEventListener(waiter);
				assertNotNull("event should not be null", event);
				assertEquals(req, event.request());
				val = event.returnValue();
				assertNotNull("value should not be null", val);
				assertEquals("return value must be 123", val.virtualMachine().mirrorOf(123L), val);
				erm.deleteEventRequest(req);
			}
		} 
		catch (InterruptedException e) {
			assertTrue("thrown exception mean failure", false);
		}
	}			
}
