| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.api.debugger.jpda; |
| |
| import java.io.IOException; |
| |
| import com.sun.jdi.connect.IllegalConnectorArgumentsException; |
| import junit.framework.Test; |
| import org.netbeans.api.debugger.DebuggerManager; |
| import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent; |
| import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener; |
| import org.netbeans.junit.NbTestCase; |
| |
| /** |
| * Tests line breakpoints at various places. |
| * |
| * @author Maros Sandor, Jan Jancura |
| */ |
| public class LineBreakpointTest extends NbTestCase { |
| |
| private static final String TEST_APP = Utils.getURL(System.getProperty ("test.dir.src") + |
| "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"); |
| private static final String TEST_APP_PATH = System.getProperty ("test.dir.src") + |
| "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"; |
| |
| private JPDASupport support; |
| |
| |
| public LineBreakpointTest (String s) { |
| super (s); |
| } |
| |
| public static Test suite() { |
| return JPDASupport.createTestSuite(LineBreakpointTest.class); |
| } |
| |
| public void testConditionalBreakpoint() throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete ( |
| bp.getStopLine("condition1"), |
| "x==22", |
| JPDABreakpointEvent.CONDITION_FALSE |
| ); |
| doTestBreakpointComplete ( |
| bp.getStopLine("condition2"), |
| "x==60", |
| JPDABreakpointEvent.CONDITION_TRUE |
| ); |
| } |
| |
| public void testMultipleLineBreakpoints () throws Exception { |
| try { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| LineBreakpoint[] lb = bp.getBreakpoints().toArray(new LineBreakpoint[0]); |
| { |
| LineBreakpoint b; |
| b = lb[4]; |
| lb[4] = lb[2]; |
| lb[2] = b; |
| } |
| /* |
| LineBreakpoint lb1 = LineBreakpoint.create (TEST_APP, 32); |
| LineBreakpoint lb2 = LineBreakpoint.create (TEST_APP, 37); |
| LineBreakpoint lb3 = LineBreakpoint.create (TEST_APP, 109); |
| lb3.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$Inner"); |
| LineBreakpoint lb4 = LineBreakpoint.create (TEST_APP, 92); |
| lb4.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$InnerStatic"); |
| LineBreakpoint lb5 = LineBreakpoint.create (TEST_APP, 41); |
| */ |
| DebuggerManager dm = DebuggerManager.getDebuggerManager (); |
| for (int i = 0; i < lb.length; i++) { |
| dm.addBreakpoint (lb[i]); |
| } |
| |
| TestBreakpointListener[] tb = new TestBreakpointListener[lb.length]; |
| for (int i = 0; i < lb.length; i++) { |
| tb[i] = new TestBreakpointListener (lb[i]); |
| lb[i].addJPDABreakpointListener (tb[i]); |
| } |
| support = JPDASupport.attach ( |
| "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" |
| ); |
| JPDADebugger debugger = support.getDebugger(); |
| |
| for (int j = 0; j < lb.length; j++) { |
| support.waitState (JPDADebugger.STATE_STOPPED); // j-th breakpoint hit |
| assertEquals ( |
| "Debugger stopped at wrong line for breakpoint " + j, |
| lb[j].getLineNumber (), |
| debugger.getCurrentCallStackFrame ().getLineNumber (null) |
| ); |
| for (int i = j+1; i < tb.length; i++) { |
| tb[i].checkNotNotified(); |
| } |
| if (j < lb.length - 1) { |
| support.doContinue(); |
| } |
| } |
| |
| for (int i = 0; i < tb.length; i++) { |
| tb[i].checkResult (); |
| } |
| for (int i = 0; i < tb.length; i++) { |
| dm.removeBreakpoint (lb[i]); |
| } |
| support.doContinue (); |
| support.waitState (JPDADebugger.STATE_DISCONNECTED); |
| } finally { |
| if (support != null) support.doFinish (); |
| } |
| } |
| |
| public void testStaticBlockBreakpoint() throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete(bp.getStopLine("staticx")); |
| doTestBreakpointComplete(bp.getStopLine("staticx2")); |
| } |
| |
| public void testStaticInnerClassBreakpoint() throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete(bp.getStopLine("IS1")); |
| doTestBreakpointComplete(bp.getStopLine("IS2")); |
| doTestBreakpointComplete(bp.getStopLine("IS3")); |
| } |
| |
| public void testMainLineBreakpoint() throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete(bp.getStopLine("M1")); |
| } |
| |
| public void testConstructorLineBreakpoint() throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete(bp.getStopLine("C1")); |
| } |
| |
| public void testInnerLineBreakpoint () throws Exception { |
| Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); |
| doTestBreakpointComplete (bp.getStopLine("I1")); |
| doTestBreakpointComplete (bp.getStopLine("I2")); |
| doTestBreakpointComplete (bp.getStopLine("I3")); |
| } |
| |
| private void doTestBreakpointComplete ( |
| int line, |
| String condition, |
| int conditionResult |
| ) throws IOException, IllegalConnectorArgumentsException, |
| DebuggerStartException { |
| try { |
| LineBreakpoint lb = doTestBreakpoint ( |
| line, |
| condition, |
| conditionResult |
| ); |
| if ( condition == null || |
| conditionResult == JPDABreakpointEvent.CONDITION_TRUE |
| ) { |
| support.doContinue(); |
| support.waitState (JPDADebugger.STATE_DISCONNECTED); |
| } |
| DebuggerManager.getDebuggerManager ().removeBreakpoint (lb); |
| } finally { |
| if (support != null) support.doFinish(); |
| } |
| } |
| |
| private void doTestBreakpointComplete (int line) throws IOException, |
| IllegalConnectorArgumentsException, DebuggerStartException { |
| doTestBreakpointComplete ( |
| line, |
| null, |
| JPDABreakpointEvent.CONDITION_NONE |
| ); |
| } |
| |
| private LineBreakpoint doTestBreakpoint ( |
| int line, |
| String condition, |
| int conditionResult |
| ) throws IOException, IllegalConnectorArgumentsException, |
| DebuggerStartException { |
| JPDASupport.removeAllBreakpoints (); |
| LineBreakpoint lb = LineBreakpoint.create (TEST_APP, line); |
| /* |
| if (73 <= line && line <= 98) { |
| lb.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$InnerStatic"); |
| } else if (100 <= line && line <= 115) { |
| lb.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$Inner"); |
| } |
| */ |
| lb.setCondition (condition); |
| TestBreakpointListener tbl = new TestBreakpointListener |
| (lb, conditionResult); |
| lb.addJPDABreakpointListener (tbl); |
| DebuggerManager.getDebuggerManager ().addBreakpoint (lb); |
| |
| support = JPDASupport.attach ( |
| "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" |
| ); |
| |
| if ( condition == null || |
| conditionResult == JPDABreakpointEvent.CONDITION_TRUE |
| ) { |
| support.waitState (JPDADebugger.STATE_STOPPED); |
| } else { |
| support.waitState (JPDADebugger.STATE_DISCONNECTED); |
| } |
| |
| tbl.checkResult (); |
| return lb; |
| } |
| |
| |
| /** |
| * Tests debugger's ability to make difference between different projects |
| * with the same classes while getting the locations during class-loaded event. |
| * |
| * 1. The user creates 2 classes: ${test.dir.src}/.../LineBreakpointApp.java |
| * and ${test.dir.src_2}/.../LineBreakpointApp.java |
| * 2. Then set a breakpoint in ${test.dir.src_2}/.../LineBreakpointApp.java. |
| * |
| * Debugger should stop _only_ in the second project. If debugger stopped in |
| * the first one, then assertion violation would arise because of source path |
| * equality test. |
| */ |
| public void testBreakpointUnambiguity1 () throws Exception { |
| try { |
| Utils.BreakPositions bp = Utils.getBreakPositions(System.getProperty ("test.dir.src") + |
| "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"); |
| LineBreakpoint lb1 = LineBreakpoint.create (TEST_APP, bp.getStopLine("condition1")); |
| // lb1.setSourceRoot(System.getProperty ("test.dir.src")); |
| DebuggerManager dm = DebuggerManager.getDebuggerManager (); |
| dm.addBreakpoint (lb1); |
| |
| TestBreakpointListener tb1 = new TestBreakpointListener (lb1); |
| lb1.addJPDABreakpointListener (tb1); |
| |
| support = JPDASupport.attach ( |
| "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" |
| ); |
| JPDADebugger debugger = support.getDebugger(); |
| |
| support.waitState (JPDADebugger.STATE_STOPPED); // breakpoint hit, the source root is correct |
| assertEquals ( |
| "Debugger stopped at wrong line", |
| lb1.getLineNumber (), |
| debugger.getCurrentCallStackFrame ().getLineNumber (null) |
| ); |
| |
| tb1.checkResult (); |
| support.doContinue(); |
| support.waitState (JPDADebugger.STATE_DISCONNECTED); |
| dm.removeBreakpoint (lb1); |
| support.doFinish (); |
| /* |
| // Second run - BP should not be hit with a different source root - viz testBreakpointUnambiguity2() |
| support = null; |
| lb1 = LineBreakpoint.create (TEST_APP, 39); |
| lb1.setSourceRoot(System.getProperty ("test.dir.src")+"_2"); |
| dm = DebuggerManager.getDebuggerManager (); |
| dm.addBreakpoint (lb1); |
| |
| tb1 = new TestBreakpointListener (lb1); |
| lb1.addJPDABreakpointListener (tb1); |
| |
| support = JPDASupport.attach ( |
| "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" |
| ); |
| debugger = support.getDebugger(); |
| |
| support.waitState (JPDADebugger.STATE_STOPPED); // Stopped or disconnected |
| assertEquals( |
| "Debugger should not stop on BP with faked source root", |
| debugger.getState(), |
| JPDADebugger.STATE_DISCONNECTED |
| ); |
| tb1.checkNotNotified(); |
| dm.removeBreakpoint (lb1); |
| */ |
| } finally { |
| if (support != null) support.doFinish (); |
| } |
| } |
| |
| /** |
| * Tests debugger's ability to make difference between different projects |
| * with the same classes while getting the locations during class-loaded event. |
| * |
| * 1. The user creates 2 classes: ${test.dir.src}/.../LineBreakpointApp.java |
| * and ${test.dir.src_2}/.../LineBreakpointApp.java |
| * 2. Then set a breakpoint in ${test.dir.src_2}/.../LineBreakpointApp.java. |
| * |
| * Debugger should stop _only_ in the second project. If debugger stopped in |
| * the first one, then assertion violation would arise because of source path |
| * equality test. |
| */ |
| public void testBreakpointUnambiguity2 () throws Exception { |
| try { |
| Utils.BreakPositions bp = Utils.getBreakPositions(System.getProperty ("test.dir.src") + |
| "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"); |
| LineBreakpoint lb1 = LineBreakpoint.create( |
| Utils.getURL(System.getProperty ("user.home") + // intentionally bad path |
| java.io.File.separator + |
| "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"), bp.getStopLine("condition1")); |
| //lb1.setSourceRoot(System.getProperty ("test.dir.src") + "_2"); |
| DebuggerManager dm = DebuggerManager.getDebuggerManager (); |
| dm.addBreakpoint (lb1); |
| |
| TestBreakpointListener tb1 = new TestBreakpointListener (lb1); |
| lb1.addJPDABreakpointListener (tb1); |
| |
| support = JPDASupport.attach ( |
| "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" |
| ); |
| JPDADebugger debugger = support.getDebugger(); |
| |
| support.waitState (JPDADebugger.STATE_STOPPED); // Stopped or disconnected |
| assertEquals( |
| "Debugger should not stop on BP with faked source root", |
| debugger.getState(), |
| JPDADebugger.STATE_DISCONNECTED |
| ); |
| |
| tb1.checkNotNotified(); |
| dm.removeBreakpoint (lb1); |
| } finally { |
| if (support != null) support.doFinish (); |
| } |
| } |
| |
| // innerclasses ............................................................ |
| |
| private class TestBreakpointListener implements JPDABreakpointListener { |
| |
| private LineBreakpoint lineBreakpoint; |
| private int conditionResult; |
| |
| private JPDABreakpointEvent event; |
| private AssertionError failure; |
| |
| public TestBreakpointListener (LineBreakpoint lineBreakpoint) { |
| this (lineBreakpoint, JPDABreakpointEvent.CONDITION_NONE); |
| } |
| |
| public TestBreakpointListener ( |
| LineBreakpoint lineBreakpoint, |
| int conditionResult |
| ) { |
| this.lineBreakpoint = lineBreakpoint; |
| this.conditionResult = conditionResult; |
| } |
| |
| public void breakpointReached (JPDABreakpointEvent event) { |
| try { |
| checkEvent (event); |
| } catch (AssertionError e) { |
| failure = e; |
| } catch (Throwable e) { |
| failure = new AssertionError (e); |
| } |
| } |
| |
| private void checkEvent (JPDABreakpointEvent event) { |
| this.event = event; |
| assertEquals ( |
| "Breakpoint event: Wrong source breakpoint", |
| lineBreakpoint, |
| event.getSource () |
| ); |
| assertNotNull ( |
| "Breakpoint event: Context thread is null", |
| event.getThread () |
| ); |
| |
| int result = event.getConditionResult (); |
| if ( result == JPDABreakpointEvent.CONDITION_FAILED && |
| conditionResult != JPDABreakpointEvent.CONDITION_FAILED |
| ) |
| failure = new AssertionError (event.getConditionException ()); |
| else |
| if (result != conditionResult) |
| failure = new AssertionError ( |
| "Unexpected breakpoint condition result: " + result |
| ); |
| } |
| |
| public void checkResult () { |
| if (event == null) { |
| CallStackFrame f = support.getDebugger (). |
| getCurrentCallStackFrame (); |
| int ln = -1; |
| if (f != null) { |
| ln = f.getLineNumber (null); |
| } |
| throw new AssertionError ( |
| "Breakpoint was not hit (listener was not notified) " + ln |
| ); |
| } |
| if (failure != null) throw failure; |
| } |
| |
| public void checkNotNotified() { |
| if (event != null) { |
| JPDAThread t = event.getThread(); |
| throw new AssertionError ( |
| "Breakpoint was hit (listener was notified) in thread " + t |
| ); |
| } |
| if (failure != null) throw failure; |
| } |
| } |
| } |