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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
import org.eclipse.jdt.debug.core.IJavaPrimitiveValue;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.tests.AbstractDebugTest;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;

/**
 * Tests method breakpoints.
 */
public class MethodBreakpointTests extends AbstractDebugTest {

	/**
	 * Constructor
	 * @param name
	 */
	public MethodBreakpointTests(String name) {
		super(name);
	}

	/**
	 * @throws Exception
	 */
	public void testEntryAndExitBreakpoints() throws Exception {
		String typeName = "DropTests";
		List<IJavaMethodBreakpoint> bps = new ArrayList<IJavaMethodBreakpoint>();
		// method 4 - entry
		bps.add(createMethodBreakpoint(typeName, "method4", "()V", true, false));
		// method 1 - exit
		bps.add(createMethodBreakpoint(typeName, "method1", "()V", false, true));


		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName);
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			// onto the next breakpoint
			thread = resume(thread);

			hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit exit breakpoint second", bps.get(1), hit);

		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests the 'stop in main' launching preference
	 * {@link IJavaLaunchConfigurationConstants#ATTR_STOP_IN_MAIN}
	 * @throws Exception
	 */
	public void testStopInMain() throws Exception {
		String typeName = "DropTests";
		ILaunchConfiguration config = getLaunchConfiguration(typeName);
		assertNotNull("Could not find launch config", config);
		ILaunchConfigurationWorkingCopy wc = config.copy("DropTests - Stop in main");
		wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, true);
		config = wc.doSave();

		IJavaThread thread= null;
		try {
			thread= launchAndSuspend(config);
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);

			IJavaStackFrame frame = (IJavaStackFrame)thread.getTopStackFrame();
			assertTrue("Should be in 'main'", frame.getMethodName().equals("main") && frame.isStatic());

		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests disabled method entry and exit breakpoints
	 * @throws Exception
	 */
	public void testDisabledEntryAndExitBreakpoints() throws Exception {
		String typeName = "DropTests";
		// method 4 - entry
		IBreakpoint bp1 = createMethodBreakpoint(typeName, "method4", "()V", true, false);
		bp1.setEnabled(false);
		// method 1 - exit
		IBreakpoint bp2 = createMethodBreakpoint(typeName, "method1", "()V", false, true);
		bp2.setEnabled(false);

		IJavaDebugTarget debugTarget= null;
		try {
			debugTarget= launchAndTerminate(typeName);
		} finally {
			terminateAndRemove(debugTarget);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests that a method is NOT hit in an inner class
	 * @throws Exception
	 */
	public void testInnerClassNotHit() throws Exception {
		String typeNamePattern = "A";
		List<IJavaMethodBreakpoint> bps = new ArrayList<IJavaMethodBreakpoint>();
		// method b - entry
		bps.add(createMethodBreakpoint(typeNamePattern, "b", "()V", true, false));


		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeNamePattern);
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);


			resumeAndExit(thread);

		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests that a given method IS hit in an inner class
	 * @throws Exception
	 */
	public void testInnerClassesHit() throws Exception {
		String typeNamePattern = "A*";
		List<IJavaMethodBreakpoint> bps = new ArrayList<IJavaMethodBreakpoint>();
		// method b - entry
		bps.add(createMethodBreakpoint(typeNamePattern, "b", "()V", true, false));


		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint("A");
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			thread= resume(thread);
			hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			thread= resume(thread);
			hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			thread= resume(thread);
			hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			resumeAndExit(thread);
		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests the hit count for a method breakpoint suspends when reached
	 * @throws Exception
	 */
	public void testHitCountEntryBreakpoint() throws Exception {
		String typeName = "MethodLoop";
		IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, "calculateSum", "()V", true, false);
		bp.setHitCount(3);

		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName);
			assertNotNull("Method entry breakpoint not hit within timeout period", thread);

			IJavaStackFrame frame = (IJavaStackFrame)thread.getTopStackFrame();
			IVariable var = findVariable(frame, "sum");
			assertNotNull("Could not find variable 'sum'", var);

			IJavaPrimitiveValue value = (IJavaPrimitiveValue)var.getValue();
			assertNotNull("variable 'sum' has no value", value);
			int iValue = value.getIntValue();
			assertTrue("value of 'sum' should be '3', but was " + iValue, iValue == 3);

			bp.delete();
		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests that the a method exit breakpoint suspends when its hit count is reached
	 * @throws Exception
	 */
	public void testHitCountExitBreakpoint() throws Exception {
		String typeName = "MethodLoop";
		IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, "calculateSum", "()V", false, true);
		bp.setHitCount(3);

		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName);
			assertNotNull("Method exit breakpoint not hit within timeout period", thread);

			IJavaStackFrame frame = (IJavaStackFrame)thread.getTopStackFrame();
			IVariable var = findVariable(frame, "sum");
			assertNotNull("Could not find variable 'sum'", var);

			IJavaPrimitiveValue value = (IJavaPrimitiveValue)var.getValue();
			assertNotNull("variable 'sum' has no value", value);
			int iValue = value.getIntValue();
			assertTrue("value of 'sum' should be '6', but was " + iValue, iValue == 6);

			bp.delete();
		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests an inclusive thread filter on a method breakpoint
	 * @throws Exception
	 */
	public void testThreadFilterInclusive() throws Exception {
		String typeName = "MethodLoop";
		IJavaMethodBreakpoint methodBp = createMethodBreakpoint(typeName, "calculateSum", "()V", true, false);
		createLineBreakpoint(18, typeName);

		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName, false);
			assertNotNull("breakpoint not hit within timeout period", thread);

			IJavaStackFrame frame = (IJavaStackFrame)thread.getTopStackFrame();

			// set a thread filter (to the main thread)
			methodBp.setThreadFilter(thread);

			thread = resume(thread);
			assertNotNull("breakpoint not hit", thread);

			frame = (IJavaStackFrame)thread.getTopStackFrame();
			assertEquals("should be in 'calucateSum'", "calculateSum", frame.getMethodName());

		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests an exclusive thread filter on a method breakpoint
	 * @throws Exception
	 */
	public void testThreadFilterExclusive() throws Exception {
		String typeName = "MethodLoop";
		IJavaMethodBreakpoint methodBp = createMethodBreakpoint(typeName, "calculateSum", "()V", true, false);
		createLineBreakpoint(18, typeName);

		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName, false);
			assertNotNull("breakpoint not hit within timeout period", thread);

			thread.getTopStackFrame();

			// set a thread filter (*not* the main thread)
			IThread[] threads = thread.getDebugTarget().getThreads();
			for (int i = 0; i < threads.length; i++) {
				IThread thread2 = threads[i];
				if (!thread2.equals(thread)) {
					methodBp.setThreadFilter((IJavaThread)thread2);
					break;
				}
			}
			assertNotNull("Did not set thread filter",methodBp.getThreadFilter((IJavaDebugTarget)thread.getDebugTarget()));

			resumeAndExit(thread);
		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Test for bug 33551
	 * Tests that a method breakpoint is hit properly in the default package
	 * @throws Exception
	 */
	public void testEntryDefaultPackageReturnType() throws Exception {
		String typeName = "DefPkgReturnType";
		IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, "self", "()LDefPkgReturnType;", true, false);

		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName);
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint", bp,hit);

		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Test for bug 43611
	 * Tests that the debug model presentation is returning the correct signature for a specific method breakpoint
	 * @throws Exception
	 */
	public void testLabelWithoutSignature() throws Exception {
		IDebugModelPresentation modelPresentation = DebugUITools.newDebugModelPresentation();
		try {
			String typeName = "DefPkgReturnType";
			IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, "self", null, true, false);
			String label = modelPresentation.getText(bp);
			assertTrue(label.indexOf("self") >= 0);
		} finally {
			removeAllBreakpoints();
			modelPresentation.dispose();
		}
	}

	/**
	 * Test for bug 43611
	 * Tests that the debug model presentation handles a label with no name for a specific method breakpoint
	 * @throws Exception
	 */
	public void testLabelWithoutMethodName() throws Exception {
		IDebugModelPresentation modelPresentation = DebugUITools.newDebugModelPresentation();
		try {
			String typeName = "DefPkgReturnType";
			IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, null, "()LDefPkgReturnType;", true, false);
			String label = modelPresentation.getText(bp);
			assertTrue(label.indexOf(typeName) >= 0);
		} finally {
			removeAllBreakpoints();
			modelPresentation.dispose();
		}
	}

	/**
	 * Test for bug 43611
	 * Tests that the debug model presentation handles no signature or method name for a specific
	 * method breakpoint
	 * @throws Exception
	 */
	public void testLabelWithoutSigOrMethodName() throws Exception {
		IDebugModelPresentation modelPresentation = DebugUITools.newDebugModelPresentation();
		try {
			String typeName = "DefPkgReturnType";
			IJavaMethodBreakpoint bp = createMethodBreakpoint(typeName, null, null, true, false);
			String label = modelPresentation.getText(bp);
			assertTrue(label.indexOf(typeName) >= 0);
		} finally {
			removeAllBreakpoints();
			modelPresentation.dispose();
		}
	}

	/**
	 * Tests that a specific method breakpoint is skipped when set to do so
	 * @throws Exception
	 */
	public void testSkipMethodBreakpoint() throws Exception {
		String typeName = "DropTests";
		List<IJavaMethodBreakpoint> bps = new ArrayList<IJavaMethodBreakpoint>();
		// method 4 - entry
		bps.add(createMethodBreakpoint(typeName, "method4", "()V", true, false));
		// method 1 - exit
		bps.add(createMethodBreakpoint(typeName, "method1", "()V", false, true));


		IJavaThread thread= null;
		try {
			thread= launchToBreakpoint(typeName);
			assertNotNull("Breakpoint not hit within timeout period", thread);

			IBreakpoint hit = getBreakpoint(thread);
			assertNotNull("suspended, but not by breakpoint", hit);
			assertEquals("should hit entry breakpoint first", bps.get(0),hit);

			getBreakpointManager().setEnabled(false);
			resumeAndExit(thread);
		} finally {
			terminateAndRemove(thread);
			removeAllBreakpoints();
			getBreakpointManager().setEnabled(true);
		}
	}
}
